Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Работа с дробными числами (https://javascript.ru/forum/misc/11417-rabota-s-drobnymi-chislami.html)

DMH 22.08.2010 18:05

Работа с дробными числами
 
<script>

function xxx(b) {

alert(b);

if (b < 1) { b = b + 0.1; setTimeout(function() { xxx(b); }, 1000); }

}
</script>

<input type="button" value="Send" onclick="xxx(0.1)">

В алерте получаю -
0.1
0.2
0.3000...0004
0.4
0.5
0.6
0.7
0.7999...9999
0.8999...9999
0.9999...9999
1.0999...9999

Причём по всех браузерах одно и тоже.
Решил проблему так: b = (b*10 + 1)/10;
Но всё же интересно узнать, почему 0.2 + 0.1 != 0.3.

Octane 22.08.2010 22:51

http://www.rsdn.ru/article/alg/float.xml

DMH 23.08.2010 09:07

Можно даже проще -
alert(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)

получим 0.999...999;
А вот если проделать тоже самое в c#, то результат будет верный -
Response.Write(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)

получим 1.

Из той статьи -
Цитата:

То есть, с математической точки зрения, операция сложения чисел с плавающей запятой не ассоциативна: (a + b) + c != a + (b + c).
+ округление формата.
Более менее ясно с математической стороны, но с логической стороны не могу принять сей факт, в школе учили, что 0.1+0.1=0.2, а не 0.3.

Octane 23.08.2010 09:19

А еще в школе учили, что множество действительных (вещественных) чисел бесконечно, поэтому представить действительное число в двоичном виде можно только с ограниченной точностью (8, 16, 32, 64 байт).

Riim 23.08.2010 09:33

Цитата:

Сообщение от DMH
А вот если проделать тоже самое в c#

в js числа занимают 8 байт (float64 (64 - количество бит)), в C# float занимает 32 байта, причем когда вы пишите "0.1" создается не float а double:
Response.Write(0.1 is float);
Response.Write("<br />");
Response.Write(0.1 is double);

т. е. 64 байта. Для создания float нужно "f" или "F" после числа поставить:
Response.Write(0.1f is float);


Неточные вычисления можно получить и в C#.

DMH 23.08.2010 13:49

В примере с c# можно и так написать - 0.1f+0.1f+..., получим ту же единицу, даже можем 12 нулей дорисовать, получим 1E-12, что для обычных вычислений вполне достаточно.
А с js нашёл пример прямо на этом сайте - http://javascript.ru/basic/types#netochnye-vychisleniya
Вобщем с float64 приходится отказываться от дроби, либо округлять неточности, короче дополнительная работа.


Часовой пояс GMT +3, время: 00:17.