Если вы оцениваете
(Math.PI).ToString("G51")
результат
"3,141592653589793115997963468544185161590576171875"
Math.Pi
правильно до 15-го знака после запятой, что соответствует точности double
. «G17» используется для кругового обхода, поэтому я ожидал, что ToString
остановится после «G17», но вместо этого он продолжал выдавать числа до «G51».
В. Поскольку цифры после 15-го десятичного знака выходят за пределы точности, обеспечиваемой 53 битами мантиссы, как вычисляются остальные цифры?
Пожалуйста, запишите результат 1/3 в базе 10. Подсказка: вы не можете. Вы можете записывать только комбинации степеней 10 (например, 10 ^ -1 (он же 0,1), 2 * 10 ^ -1 (0,2), 10 ^ -2 (0,01) и т. д. Таким образом, 0,23 возможно, но 1/3 нет. 't 0,333, и даже не 0,334, по крайней мере, не точно Точно так же с двоичным вы можете использовать только комбинации степеней 2.
@ProgrammingLlama, @Richard Это не моя точка зрения. Двойная мантисса имеет 53 бита, что соответствует 15 десятичным знакам. Так откуда же берется шум после 17-го знака после запятой? ToString("G51")
их выдумывает?
Я проголосовал за открытие. В предложенном дубликате есть много ответов, но я не думаю, что какой-либо из них напрямую касается этого вопроса. Обратите внимание, что десятичные цифры кажутся просто точным значением с основанием 10 приблизительного двойного числа.
Метод .ToString("G51")
использует «школьную математику». Сначала он берет целую часть, затем умножает Remainder
на 10, использует целую часть этого вычисления и умножает Remainder
часть на 10.
Это будет продолжаться до тех пор, пока есть остаток и до 51
десятичных цифр.
Поскольку у double
есть показатель степени, он будет иметь остаток примерно с 18 десятичными цифрами, что дает следующую цифру в методе ToString
.
Однако, как вы видели, часть Remainder
не является точной, а просто результатом математической функции.
Двойник имеет 53-битную мантисса, которая соответствует 15 десятичным знакам.
Двойник имеет 53-битную мантисса, которая соответствует примерно 15 десятичным знакам.
Math.Pi усекается до 53 бит в двоичном формате, что не совсем равно
3.1415926535897
но это также не совсем равно
3.14159265358979
, так далее.
Точно так же, как 1/3 — это не совсем 0,3 или 0,33 и т. д.
Если вы продолжите десятичное расширение достаточно долго, оно в конечном итоге прекратится или начнет повторяться, поскольку Math.PI, в отличие от π, является рациональным числом.
И как вы можете убедиться с типом BigRational
using System.Numerics;
var r = new BigRational(Math.PI);
BigRational dem;
BigRational.NumDen(r, out dem);
var num = r * dem;
Console.WriteLine(num);
Console.WriteLine("-----------------");
Console.WriteLine(dem);
это
884279719003555
---------------
281474976710656
И поскольку знаменатель является степенью числа 2 (что должно быть, поскольку Math.PI имеет двоичную мантисса и, следовательно, завершающее представление в базе 2). Следовательно, он также имеет завершающее представление в базе 10, что и было дано (Math.PI).ToString("G51")
:
3.141592653589793115997963468544185161590576171875
в качестве
Console.WriteLine(r == BigRational.Parse("3.141592653589793115997963468544185161590576171875"));
выходы
True
точное значение 884279719003555/281474976710656 равно 3,141592653589793115997963468544185161590576171875
См. 0.30000000000000004.com