Skip to content

IsPowerOfTwo has bugs #893

@Rudxain

Description

@Rudxain

JS doesn't use fixed-point int arithmetic, it uses floating-point "rationals". JS bitwise ops use "modulo" internally (specifically mod 2 ** 32), which removes all bits with an index greater than 31. So the bitwise int implementation doesn't work because IsPowerOfTwo((2 ** 53 - 1) * 2 ** 32) and IsPowerOfTwo(Infinity) return true.

I propose using trial divison by 2, since it's simple and most engines will optimize it as a simple FPFP exponent decrement. And using a "guard clause" to prevent Infinity or NaN from messing up the output:

const IsPowerOfTwo = n =>
{
  n = n?.valueOf(); //coerce to primitive, this ensures "object-wrapped" Numbers are recognized by `isFinite` method
  //technically, negative powers of 2 are valid, but this uses a narrower definiton (only unsigneds)
  if (!Number.isFinite(n) || n < 2) return false;
  //strict equality is the same as "loose" eq, when both operands are of the same type
  while (n % 2 == 0) n /= 2;
  return n == 1
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions