Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   Баг с простыми арифметическими действиями (приведение типов)? (http://www.flasher.ru/forum/showthread.php?t=107652)

wvxvw 06.02.2008 18:47

Баг с простыми арифметическими действиями (приведение типов)?
 
Код:

class rendering.Line {

        private var __a:PNT;
        private var __b:PNT;
       
        private var __length:Number = Number.NaN;
        private var __height:Number = Number.NaN;
        private var __width:Number = Number.NaN;
        private var __angle:Number = Number.NaN;
       
        public function Line(pa:PNT, pb:PNT) {
                __a = pa;
                __b = pb;
                __width = __b.x - __a.x;
                __height = __b.y - __a.y;
                trace(pa.x + ' : ' + pa.y + ' : ' + pb.x + ' : ' + pb.y);
                trace(__b.x == __a.x);
                trace('angle: ' + __angle + ' : ' + __height + ' : ' + __width);
                __length = Math.sqrt(__width * __width + __height * __height);
                __angle = Math.atan(__width / __height);
        }
}

Код:

class rendering.PNT extends Array {

        public function PNT(xx:Number, yy:Number) {
                this.push(xx);
                this.push(yy);
        }
       
        public function set x(p:Number):Void {
                this[0] = Math.round(p);
        }
        public function get x():Number {
                return this[0];
        }
        public function set y(p:Number):Void {
                this[1] = Math.round(p);
        }
        public function get y():Number {
                return this[1];
        }
}

Похоже на баг компайлера... или я чего-то не понимаю =/

Уже чего только не делал...
Код:

new Line(new PNT(130,130), new PNT(30,130));
И в трейс выдается:
angle: NaN : -2.8421709430404e-14 : -100
(вместо -2.8421709430404e-14 должно быть 0)

iNils 06.02.2008 18:59

Мой трейс
Цитата:

130 : 130 : 30 : 130
false
angle: NaN : 0 : -100

MrPoma 06.02.2008 19:08

опустите трейс в низ конструктора и будет вам сказка

в результате трейс:
Цитата:

130 : 130 : 30 : 130
false
angle: -1.5707963267949 : 0 : -100

wvxvw 06.02.2008 19:14

Перезапустил комп... откомпилировал флешем и мтаском... по прежнему такой же результат... Самое непонятное, что с некоторыми числами проблем не возникает =/

Цитата:

опустите трейс в низ конструктора и будет вам сказка

в результате трейс:
А при чем то, где находится трейс? Мне угол не интересен... Плохо то, что 130-130 почему-то получается -2.8421709430404e-14, а не 0...

iNils 06.02.2008 19:22

Числа которые передавались в "new Line(new PNT(..." были получены в результате неких мат операций, но для примера ты вывел их в трейс и дал их нам, а сам продолжаешь использовать результаты мат операций?

chingachgoog 06.02.2008 19:25

Цитата:

Сообщение от wvxvw
Плохо то, что 130-130 почему-то получается -2.8421709430404e-14, а не 0...

Мантисса 15 знаков...

Цитата:

Сообщение от Гурский
Если не знать особенностей представления чисел на компьютере, то возможны очень интересные сюрпризы. Например, попробуем вычислить значения двух алгебраически абсолютно идентичных выражений и посмотрим, совпадут ли результаты:
Код:

var a=500000;
var expr1=a/(Math.pow(a+1,1/2)+Math.pow(a,1/2));
var expr2=a*(Math.pow(a+1,1/2)-Math.pow(a,1/2));
trace(expr1-expr2); // Выводит: 3.72591557606938e-9

Результаты расчетов по двум идентичным формулам различаются, пусть и не значительно.Аэто означает, что если бымыпытались установить факт равенства этих выражений, используя предложение if(), то вывод был бы сделан неверно, что связано с тем, что в ActionScript два числа равны только тогда, когда равенство соблюдается для всех разрядов.
Причиной появления ошибок, подобных описанной, является то, что числа сохраняются с ограниченной точностью. Конечно, 15 знаков мантиссы достаточно для большинства расчетов. Но в некоторых случаях ошибки округления способны накапливаться, искажая результат весьма значительно.

Особый случай представляют встроенные тригонометрические функции, результаты вычислений значений которых в точках нулей и разрывов практически никогда не совпадают с математически верными:
Код:

trace(Math.sin(Math.PI)); // Выводит: 1.22460635382238e-16 (нужно -0)
trace(Math.tan(Math.PI/2)); // Выводит: 1.63317787283838e+16 (нужно —
// Infinity)

Причиной появления не совсем правильных результатов в приведенных примерах является округление мантиссы чисел до 15 знаков. Справиться с этой проблемой непосредственным образом невозможно.


iNils 06.02.2008 19:36

chingachgoog, дело не в этом, а в том, что в трейс идет число округленное, а в расчетах участвует дробное.
Вот пример где после запятой всего 13 знаков.
Код:

a = 130;
b = 130;
d = b + 0.0000000000001;
trace (d + " - " + a + " = " + (d - a));

и результат
Цитата:

130 - 130 = 1.13686837721616e-13
2 wvxvw: в классе PNT для сеттеров стоит округление для вновь вводимых значениях, а в конструкторе - нет.

wvxvw 06.02.2008 19:40

Ой... всем спасибо =) Нужно было в геттере округлять, а не в сеттере... невнимательность

iNils 06.02.2008 19:46

Цитата:

Сообщение от wvxvw
Ой... всем спасибо =) Нужно было в геттере округлять, а не в сеттере... невнимательность

Я бы оставил в сеттере, вместо того, чтобы при каждов запросе делать округление повторно, что явно производительности не прибавит. И в конструкторе бы округление сделал.

...однако мне не понятно, что было расширять здесь Array, когда нужно расширить Point.

wvxvw 06.02.2008 20:32

С первым согласен, да, правельнее будет в конструкторе округлить.
А массив - потому что в других местах понадобятся некоторые его свойства, типа конкантенации, например. А в Point есть куча всего, что я не собираюсь использовать.


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

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