Я схожу с ума или Math.Pow сломан? - PullRequest
3 голосов
/ 23 марта 2011

Я использовал базовый преобразователь из здесь и изменил его, чтобы он работал со значениями ulong, но при преобразовании больших чисел, в частности чисел выше 16677181699666568, он возвращал неверные значения.Я начал изучать это и обнаружил, что Math.Pow (3, 34) возвращает значение 16677181699666568, тогда как на самом деле 3 ^ 34 равно 16677181699666569. Таким образом, это приводит к созданию гаечного ключа для меня.Я полагаю, это просто проблема с двойной точностью в методе Pow?Является ли мое самое простое решение просто создать свой собственный Pow, который принимает значения ulong?

Если так, какой самый быстрый способ сделать Pow?Я предполагаю, что есть что-то более быстрое, чем цикл for с умножением каждый раз.

Ответы [ 5 ]

6 голосов
/ 23 марта 2011

Проблема в том, что Math.Pow возвращает double, а ближайшим double значением 16677181699666569 является 16677181699666568.

Таким образом, без участия Math.Pow:

long accurate = 16677181699666569;
double closestDouble = accurate;
// See http://pobox.com/~skeet/csharp/DoubleConverter.cs
Console.WriteLine(DoubleConverter.ToExactString(closestDouble));

Это печатает 16677181699666568.

Другими словами независимо от того, что Math.Pow делает внутренне , он не может вернуть более точный результат, чем тот, который вы получаете.

Как уже говорили другие, BigInteger.Pow ваш друг, если вы используете .NET 4.

6 голосов
/ 23 марта 2011

Вы можете использовать BigInteger.Pow .Или используйте мой метод питания для long.

5 голосов
/ 23 марта 2011

Чтение Что каждый ученый должен знать о плавающей точке

Типы с плавающей точкой являются приблизительными, округление, которое вы видите, нормальное.

Если вы хотите получить точные результаты, используйте BigInteger.

1 голос
/ 23 марта 2011

Я полагаю, что это просто проблема с двойной точностью в методе Pow?

Да.

Это мое самое простое решение - создать свой собственныйПау, который принимает значения ulong?

Вы можете использовать BigInteger.Pow.

0 голосов
/ 23 марта 2011

Если вы используете .NET Framework 4, Microsoft включила новый класс BigInteger, который позволяет вам манипулировать большими числами.

http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx

Кроме того, вы можете использовать хорошую библиотеку, созданную кем-то другим:

http://intx.codeplex.com/ (библиотека IntX)

...