Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Баги флеша при работе с дробными числами (http://www.flasher.ru/forum/showthread.php?t=129480)

xjack 02.09.2009 16:26

Баги флеша при работе с дробными числами
 
Приветствую всех. Столкнулся с проблемой, попортившей немало крови а именно:
Флеш некорректно выполняет арифметические операции над некоторыми отдельно взятыми числами. Например - при вычитании из 2.3 единицу (2.3-1) получается бред вида 1.29999999.... При этом если вместо 2.3 взять 3.3, 5.3 то все ок, зато если из 5.3 вычитаем 4 (чтобы получить опять таки проблемное 1.3) получаем опять таки 1.2999999.
Похожие проблемы были с делением, например при делении 1.9/0.1 получалось не 19 а 18.9999999...... В итоге это все приводило к тому что при последующих манипуляциях с числами получались реально неверные результаты, и я никак н мог понять в чем дело.
Да, проверил это на других SDK - все тоже самое. Кто нибудь сталкивался с подобным?

Dezar 02.09.2009 16:31

сталкивался и сталкиваюсь...
еще пытаюсь сам понять что за фигня)))

xjack 02.09.2009 16:35

Вот блин =)) И как теперь быть, когда в программе сплошные вычисления?

Dezar 02.09.2009 16:41

я тем же вопросом озадачен ))

VVall 02.09.2009 16:45

Этот вопрос часто обсуждается, используйте поиск по форуму.

random13 02.09.2009 16:48

а если арифметические действия будут происходить с числами у которых после запятой около 4-5 знаков тоже будет врать?

Волгоградец 02.09.2009 16:50

Это не баг флэша - это обычное поведение floating point. Так, например нельзя точно посчитать 0.1, 0.6 и т.д. Округляйте до нужного вам знака.

Dezar 02.09.2009 16:59

как это??нельзя точно посчитать 0.5 - 0.1 к примеру????????

iNils 02.09.2009 17:09

Это накопительная ошибка. Я ее встречал также в javascript и php.

xjack 02.09.2009 17:11

Не очень понятно что до чего округлять. Допустим я работаю с десятыми долями, т е мне достаточно одного знака. И как мне быть когда мне нужно к примеру 19 умножить на 0.1? Или же вышеприведенное вычитание. И чтобы всегда было без сюрпризов?

Ps Не знаю обычное ли это поведение, но я с плавающей точкой работаю не первый и даже не десятый раз (начинаю с паскаля и заканчивая .Net), но подобное виже впервые во flash.

VVall 02.09.2009 17:14

http://en.wikipedia.org/wiki/Floating_point

iNils 02.09.2009 17:14

Цитата:

но подобное виже впервые во flash.
Код:

<html>
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
        <script>
                var n = 2;
                for (i = 0; i < 10; i++) {
                        n += .1;
                }
                alert (n)
        </script>
</body>
</html>

Создайте html документ с этим кодом и получите 3.000000000000001

Волгоградец 02.09.2009 18:07

Все правильно - все основываются на одном и том же стандарте. Цитата из хэлпа:
Цитата:

Number
A data type representing an IEEE-754 double-precision floating-point number. You can manipulate primitive numeric values by using the methods and properties associated with the Number class. This class is identical to the JavaScript Number class.
В .NET то же самое...

Dezar 02.09.2009 18:24

и это жесть господа)

VVall 02.09.2009 18:48

Это не жесть, а ваше недопонимание, как компьютер работает с числами с плавающей запятой. Если интересно - почитайте статью в английской википедии, там всё очень подробно описано. IEEE-754 существует уже 24 года и сейчас является самым распространённым стандартом - повода для беспокойства нет.

switcher! 02.09.2009 18:48

немного утрированно, как мне показалось, но в тему

kackbip 02.09.2009 19:02

И все таки это следствие лени разработчиков.
Таких сюрпризов можно было бы избежать.

mry 02.09.2009 19:25

Delphi тоже иногда не любит Real
Даже Excel страдает подобным

Felicast 02.09.2009 19:52

во всех языках есть библиотеки для точных вычислений. я думаю и для ас3 тоже есть. нужно только поискать.
а вообще, для большинства задач вполне хватает той точности, которая есть

BlooDHounD 02.09.2009 21:27

так работает процессор. такое поведение абсолютно во всех языках происходит при работе с float'ами. программное обеспечение тут не причём. это зашито на аппаратном уровне.

kackbip 02.09.2009 21:56

Это можно обойти на программном уровне

Цитата:

во всех языках есть библиотеки для точных вычислений. я думаю и для ас3 тоже есть. нужно только поискать.
Как говорится - чтд. Так почему это не зашито в fp?

iNils 02.09.2009 22:06

Цитата:

Сообщение от kackbip (Сообщение 847727)
Как говорится - чтд. Так почему это не зашито в fp?

Зачем? Кстати, координаты не могу быть меньше 0.05 пикселя, так как такая точность не нужна. Это не расчеты ядерных реакторов.

murz 02.09.2009 22:36

Цитата:

так работает процессор. такое поведение абсолютно во всех языках происходит при работе с float'ами. программное обеспечение тут не причём. это зашито на аппаратном уровне.
как насчет "С", СИ крут, а все остальное реально не для точных вычислений.
Код:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
        float aaa= 2.3;
        int bbb= 1;
        float result= aaa - bbb;
        char str[123];
        sprintf(str, "%f",result);
        puts(str);//1.300000
        return EXIT_SUCCESS;
}


kackbip 03.09.2009 07:42

Расчеты могут производиться не только для определения координат. В головном сообщении этой темы указана проблема, которой лучше бы не было. Почему лучше бы не было? Потому что результат не соответствует ожидаемому, тому что диктует наш привычный десятиричный мат. аппарат. Это неизбежно приводит к багам или увеличению сроков разработки.

Яски 03.09.2009 10:40

Цитата:

Сообщение от kackbip (Сообщение 847664)
И все таки это следствие лени разработчиков.
Таких сюрпризов можно было бы избежать.

И где же вы раньше были? Как всегда появился гений, которому наплевать на 20 летние разработки математиков и программистов всего мира.

Цитата:

Сообщение от murz (Сообщение 847738)
как насчет "С", СИ крут, а все остальное реально не для точных вычислений.

Си ничем не отличается от других языков программирования — использует все те же числа с плавающей запятой. Только одно отличие — в настройках можно указать повышенную точность вычислений вещественных чисел, что означает, что все вычисления будут производиться с 80битными числами, а затем округлятся, а не обрезаться до размера переменной этого типа.

Цитата:

Сообщение от kackbip (Сообщение 847794)
Это неизбежно приводит к багам или увеличению сроков разработки.

Помоему вы накручиваете проблему, я при разработке программ очень часто имею дело с вещественными числами, ни разу это не вызывало для меня проблем. Тот факт, что вычисления с вещественными числами не соответствуют вычислениям с десятичными нужно просто учесть — это плата за скорость работы с такими числами. Например, нужно исключить из программы все сравнения с такими числами, сравнивать всегда нужно с учетом погрешности. Также нельзя складывать числа, которые сильно отличаются порядком.
В программах, в которых требуется точность вычислений не используются числа с плавающей запятой. В программах, которые работают с деньгами используются числа с фиксированной запятой — фактически каждое число умножается на 10000 для вычислений, а затем делится при выводе. Также есть вариант чисел очень высокой точности — при вычислениях точность чисел повышается автоматически.

random13 03.09.2009 11:28

Цитата:

Сообщение от iNils (Сообщение 847731)
Зачем? Кстати, координаты не могу быть меньше 0.05 пикселя, так как такая точность не нужна. Это не расчеты ядерных реакторов.

хммм а есть вопрос гео координат, там как раз важна точность десятых, сотых и тысячных

divinus 03.09.2009 11:32

как уже сказали, во флеше такая точность просто излишняя, нужна точность возьмите фортран

random13 03.09.2009 12:29

зашибись блин фортран, тогда можно будет и про флеш забыть... потому как скорость упадет в разу просто потому что буду дольше передавать инфу по externaInterface или через запросы... бред какой то

Zik. 03.09.2009 12:46

че-то не увидел в чем проблема
написал
Код AS1/AS2:

trace(1.9/0.1); // вывел 19
trace(5.3-4); // вывел 1.3
trace(2.3-1); // вывел 1.3


murz 03.09.2009 13:33

Цитата:

Сообщение от ZIK68 (Сообщение 847850)
че-то не увидел в чем проблема
написал
Код AS1/AS2:

trace(1.9/0.1); // вывел 19
trace(5.3-4); // вывел 1.3
trace(2.3-1); // вывел 1.3


Ипать, для AS2 это действительно так, а для AS3:
Код:

//18.999999999999996
//1.2999999999999998
//1.2999999999999998


amesqit 03.09.2009 13:35

2 ZIK68 и murz

и для as2 и для as3

Код AS1/AS2:

var a = 1.9/0.1;
var b = 5.3-4
var d = 2.3-1
trace(a == 19); // false
trace(b ==1.3); // false
trace(d ==1.3); // false


Zik. 03.09.2009 13:46

Код AS1/AS2:

var a = Math.ceil(1.9/0.1);
var b = ((100*5.3)-(100*4))/100;
var d = ((1000*2.3)-(1000*1))/1000;
trace(a == 19); // true
trace(b == 1.3); // true
trace(d == 1.3); // true

:p

iNils 03.09.2009 14:06

Цитата:

Это неизбежно приводит к багам или увеличению сроков разработки.
Яски все правильно сказал, проблем с этим возникать не должно Если у вас любая 10 секундная проблема создает большие сложности, значит у вас мало опыта.
Цитата:

хммм а есть вопрос гео координат, там как раз важна точность десятых, сотых и тысячных
См. выше. Умножате все на 10, 100 или 1000 и проблем нет.

amesqit 03.09.2009 14:09

Цитата:

Сообщение от ZIK68 (Сообщение 847875)
Код AS1/AS2:

var a = Math.ceil(1.9/0.1);
var b = ((100*5.3)-(100*4))/100;
var d = 2.3-1;
trace(a == 19);// true
trace(b == 1.3);// true
trace(b == 1.3);// true

:p

Добавлено через 9 минут
кстати, непонятно
почему после второй строчки третья становиться тоже true, если я с ней даже ниче не делал?

там моя опечатка была, последние 2 строчки в примере были одинаковые, а вы в своем примере это не исправили :D

Zik. 03.09.2009 14:13

исправил
опять непонятно
если
Код AS1/AS2:

var d = ((100*2.3)-(100*1))/100;

то выводит false, если замениьт на тыщу, то все тру


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

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