Да, 135,24 не могут быть представлены дважды, так как дважды использует двоичную экспоненциальную нотацию.
То есть: 135.24 может быть представлено экспоненциально в основании по 2 как 1.0565625 * 128 = (1 + 1/32 + 1/64 + 1/128 + 1/1024 + ...) * (2 ** 7).
представление не может быть сделано точно, поскольку 13524 не делится на 5. Давайте посмотрим:
135.24 = 13524/(10**2)
представление является конечным <=>
существует целое х и п, удовлетворяющих 135.24 = x/(2**n)
135.24 = x/(2**n)
13524/(10**2) = x/(2**n)
13524 * (2**n) = (10**2) * x
13524 * (2**n) = 2*2*5*5 * x
нет «5» с левой стороны, поэтому это невозможно сделать (известная как фундаментальная теорема Ари)
В общем случае конечное двоичное представление является точным, только если имеется достаточное количество «пятых» в простой факторизации десятичного числа.
Теперь самое интересное:
double delta = 0.5;
while(1 + delta > 1)
delta /= 2;
Console.WriteLine(delta);
Точность двойной отличается рядом 1, отличается около 0, а другая для некоторых больших чисел. Некоторые бинарные примеры представления в Википедии: Double precision floating point format
Но самое главное, что стек внутреннего процессора с плавающей точкой может иметь гораздо лучше точность чем 8 байт (дважды). Если номер не нужно передавать в ОЗУ и разделять до 8 байтов, мы можем получить очень хорошую точность.
Тестирование чего-то подобного на разных процессорах (AMD, Intel), языках (C, C++, C#, Java) или уровнях оптимизации компилятора может дать результаты могут быть около 1e-16, 1e-20 или даже 1e-320
Посмотрите на КСС/ассемблер/жасмин код, чтобы увидеть то, что происходит (например, для C++ g++ -S test.cpp
создает test.s
файл на ассемблере в нем)
Я предпочитаю верить число 135,24 не существуют –
Округление до одной цифры (135.2) не представляется в двоичном виде. Ближайшее представимое значение - 135.199, повторяющееся. Округление до двух цифр и выше будет округлено до 135.24, которое не представляется в двоичном виде (135.2400 ... 01). Я нахожу http://www.h-schmidt.net/FloatConverter/ полезным. – Caramiriel
В качестве примечания стороны: double не представляет целые числа больше 2 ** 52 правильно. float имеет предел точности 2 ** 23 so '(float) Math.Pow (2,24) == 16777217' Идите и попробуйте! – user2622016