Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Number изменяется на 0.999999999999999 (http://www.flasher.ru/forum/showthread.php?t=183665)

sospamom 28.08.2012 16:44

Number изменяется на 0.999999999999999
 
Здравствуйте.
Прибавляю к переменной типа Number, число [0.1]. В результате иногда прибавляется [0.1], а иногда [0.999999999999999]. Тоже самое с уменьшением.
Пример кода:
Код AS3:

package {
        import flash.display.Sprite;
        import flash.events.KeyboardEvent;
 
        public class Main extends Sprite {
 
                public function Main ()
                {
                        _volume = 0.5;
                        stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
                }
 
                private function keyDown(e:KeyboardEvent):void
                {
                        if (e.keyCode==37)
                        {
                                if (_volume != 1)
                                {
                                        _volume += 0.1;
                                        trace(_volume);
                                }
                        }
                        else if (e.keyCode==39)
                        {
                                if (_volume != 0)
                                {
                                        _volume -= 0.1;
                                        trace(_volume)
                                }
                        }
                }
 
                private var _volume:Number;
        }
}

Пример вывода:
Код:

0.4
0.30000000000000004
0.20000000000000004
0.10000000000000003
2.7755575615628914e-17
0.10000000000000003
0.20000000000000004
0.30000000000000004
0.20000000000000004


Krusty 28.08.2012 16:47

Это совершенно нормальное поведение.

zuxul 28.08.2012 16:47

Все нормально, это вещественные числа. В компутере всегда так.

-De- 28.08.2012 16:49

Числа в компьютере хранятся в двоичной системе счисления. В ней 0.1 - бесконечная периодическая дробь (как 1/3 = 0.333333... в десятичной). И так же, как при сложении и вычитании 0.3333333333 в десятичной вы бы не получали точные числа в десятичной (там ещё и последний знак округляется) - так же вы их не получаете проводя вычисления в двоичной.

Aquahawk 29.08.2012 01:16

http://habrahabr.ru/post/112953/ http://habrahabr.ru/post/130272/ Такое поведение не просто есть, а оно строго регламентировано стандартом, имя ему IEEE 754. И на самом деле, процессор даже ему не следует обычно, но делает что-то похожее. Чтобы сторого следовать стандарту надо сказать об этом процессору и тогда операции будут медленнее но строго соответствовать стандарту(но не вашим ожиданиям) т.к. некоторые значения конечных дробей в десятичной системе в двоичной бесконечны, и наоборот. Кстати из экшнскрипта заставить процессор строго следовать стандарту не получится.

Добавлено через 1 минуту
http://habrahabr.ru/post/123883/ вот ещё, комменты тоже полезны

Добавлено через 6 минут
Более того, от порядка вычисления зависит результат.
Код AS3:

var a:Number = (2+3)/7;
var b:Number = (2/7) + (3/7);
trace(a==b,a,b);

будет

Код:

false 0.7142857142857143 0.7142857142857142
Добавлено через 15 минут
Это непосредственно следует из того что точность чисел с плавающей точкой зависит от размера хранимого числа, т.е. на очень маленьких (сильно близких к нулю) и на очень больших (близких к положительной или отрицательной границе типа(часто, но ошибочно, называют бесконечностями, обозначаются +inf и -inf)) точность плохая. Так вот точность всегда плавает от размера хранимого значения, и в примере выше промежуточные результаты имеют разное значение, в первом случае пятёрка делится на 7, а во втором 2 и 3, и оба деления результаты меньше 1. Иногда совпадают, а иногда и нет. Обратите внимание в каком знаке отличие и нужна ли вам такая точность? Как правило нет. А вот если нужна то тогда применяют числа с фиксированной запятой. При том же объёме занимаемой памяти они могут хранить сильно меньший диапазон значений, но в то же время их точность фиксирована и предсказуема, а операции детерминированы(но от порядка вычислений тоже может зависеть результат, если на промежуточных значениях будут разные выходы за пределы точности). Например фиксированная запятая применяется в видеообработке для задания частоты кадров, т.к. если она будет плавать видно этого сразу не будет но видео будет плохо восприниматься. В частности в формате swf фреймрейт записан именно в формате с фиксированной запятой, что гарантирует ожидаемую точность без подвохов. Никак и ничто не может быть представлено с абсолютной точностью, вопрос в том какая будет ошибка и насколько она предсказуема.

Добавлено через 20 минут
Собственно формат то называется плавающая точка потому что точность плавает. Потому что когда вы считаете миллиарды +- одна тысячная обычно не важна, а если считаете около единицы, то одна тысячная как правило важнее.


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

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.