2016-07-14 3 views
0

В C/C++:Номер как 0.999999 округляется до 1

Мне нужно найти, если некоторые большие номера идеальные квадраты, но мой код находит номера, как 851659987045856130 быть действительным, когда +922854261,00000000487617621781778 фактический корень квадратный (в более высокая точность) и не является целым числом. Есть ли способ отсрочить округление для лучшей точности? Я знаю, что число, указанное выше, даже не имеет «идеальной квадратной последней цифры», но я хочу знать в целом, если можно проверить, действительно ли такое большое число является идеальным квадратом с разумным, но более высокая точность, чем стандартная.

+0

Google для библиотек больших номеров, например https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library –

+0

@Richard: здесь не нужна библиотека bignum: это можно сделать полностью в арифметике 'uint64_t', если вы имел алгоритм вычисления квадратных корней. – Hurkyl

+2

@ Хуркильный квадратный корень: начните с угадывания, соберите его, скорректируйте догадку, повторите до тех пор, пока не найдете или не получите решение –

ответ

-2

Усекайте результат на int, а затем умножьте его на себя, чтобы узнать, закончите ли вы исходный номер.

+0

@Matteo: Я думаю, вы оставили номер в плавающей запятой, вместо того, чтобы не вспоминать, чтобы вернуться обратно к 'uint64_t' – Hurkyl

+1

@MatteoItalia, правда? Он предлагает умножить целые числа. –

+0

Ответ по-прежнему не прав; вам нужно округлить. – Hurkyl

1

Лучшее, что нужно сделать, это использовать алгоритм с квадратным корнем. Если это число является репрезентативным для размера, который вы тестируете, вам даже не понадобится пакет арифметики с несколькими точками —, однако такой пакет будет самым легким местом для получить реализацию такого алгоритма. Фактически, он, вероятно, будет реализовывать непосредственно is_square (и может быть быстрее, чем вычисление квадратного корня).

Если вам было любопытно, что вы выполняете собственную реализацию, обычным подходом является метод Ньютона; например как видно на https://en.wikipedia.org/wiki/Integer_square_root.

1

Это не совсем так, как std::sqrt не является достаточно точным, это то, что double s не являются достаточно точными, чтобы представлять ваш вход правильно. Чтобы иметь верный результат, вы должны выполнить свою «настоящую» проверку в целочисленной арифметике.

Упрощенная альтернатива методу целочисленный квадратного корня может быть использовать результат std::sqrt как намек для точного поиска квадрата:

bool is_square(int64_t val) { 
    int64_t guess = std::sqrt(val); 
    for(int64_t g=guess;;++g) { 
     if(g*g==val) return true; 
     if(g*g>val) break; 
    } 
    for(int64_t g=guess-1;;--g) { 
     if(g*g==val) return true; 
     if(g*g<val) break; 
    } 
    return false; 
} 

Я подозреваю, что это может быть быстрее, чем «реальный вещь "в большинстве случаев, учитывая, что алгоритм квадратного корня с плавающей запятой может быть даже реализован в аппаратном обеспечении и поэтому должен дать начальную точку очень быстро (остальная часть алгоритма должна быть чрезвычайно быстрой, обе петли должны выйти после нескольких итераций) ,

Смежные вопросы