double
имеет ограничения по точности. Он использует двоичную базу для работы, хотя, означает, что большинство чисел, заканчивающихся серией нулевых битов в двоичном коде, может быть представлено точно, что имеет место для кратных exp2(int)
.
50 * exp2(50)
, например, 56294995342131200
, это C8000000000000
в шестнадцатеричном формате. Даже если количество цифр превышает ограничения точности double
, оно может быть представлено точно. Однако, если я попытаюсь сложить или вычесть 1
из этого числа, это уже не так.
double
не может представлять 56294995342131199
или 56294995342131201
, поэтому при попытке сделать это просто округляется до 56294995342131200
.
Вот почему ваш бит - 1
не работает, он все еще работает как double
, когда вы пытаетесь выполнить эту операцию. Вам придется привести остаток выражения к int64_t
перед выполнением этого вычитания.
Но другое решение - вообще не использовать exp2()
. Поскольку мы работаем с целыми числами, вы можете просто использовать побитовые операции для выполнения той же задачи. (1 << n)
даст вам те же результаты, что и exp2()
, за исключением того, что он теперь в целочисленном формате, и, поскольку вы просто умножаете это значение на n
, вы можете просто сделать (n << n)
.
Конечно, это все равно сломает черту. int64_t
может содержать только такие большие числа, как 2 63 -1 и uint64_t
2 64 -1, которые должны прерваться, когда ваш итератор достигнет n = 57
.