![](images/chestnut/misc/left.gif) |
FAQ Туториалы и часто задаваемые вопросы |
19.01.2007, 21:39
|
#1
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Математика в Blitz3D
Сколько твердили миру, что Blitz3D - не для математических расчётов, но - нет: я опять взялся писать странющую прогу, прельщённый лёгкой поддержкой графических форматов и простотой синтаксиса. То что уже было мною набрано на С++ я портировал на b3d и тут понеслось.
Пример раз:
Graphics 800,600
SetBuffer BackBuffer()
SetFont LoadFont("MS Sans Serif",20)
Local intervalx#[20]
Local temp0#,temp1#,temp2#,tempc%,b#
x#=14.143
xmax#=15.051
h#=0.242
temp0=13.417
tempc=1
While (temp0<=xmax)
temp2=temp0+h
intervalx[tempc]=temp2
temp0=temp2
tempc=tempc+1
Wend
b=intervalx[3]
If x=b
Print ""+x+"="+b
Else
Print ""+x+"<>"+b
EndIf
WaitKey()
End
Не знаю как у вас, а у меня в 1.98/1.98/1.98 скомпиленный ехе пишет, что 14.143<>14.143. И это, как видно из кода, не тривиалное переполнение буфера отладчика. Лечится например так:
Делаем "волшебную" конвертацию типов число->строка->число
Теперь обрабатываем сравниваемое число в коде выше:
Graphics 800,600
SetBuffer BackBuffer()
SetFont LoadFont("MS Sans Serif",20)
Local intervalx#[20]
Local temp0#,temp1#,temp2#,tempc%,b#
x#=14.143
xmax#=15.051
h#=0.242
temp0=13.417
tempc=1
While (temp0<=xmax)
temp2=temp0+h
intervalx[tempc]=temp2
temp0=temp2
tempc=tempc+1
Wend
b=intervalx[3]
b=Float(Str(b))
If x=b
Print ""+x+"="+b
Else
Print ""+x+"<>"+b
EndIf
WaitKey()
End
Теперь программа пишет, что "14.143=14.143".
Потрясающе! Мой 80кб-ый алгоритм прекрасно работал и обработал несколько сотен значений, пока я не получил на выходе коэффициент корреляции, превосходящий единицу! Программа сгенерировала 16-листов формата А4 вычислений. И всё это пришлось проверять вручную, затем ковыряться в логе отладчика (я впервые пожалел, что в нём нет поиска) - и всё это из-за одного числа.
Пример два:
Оператор INT в Blitz3D, в отличие от C++ не отбрасывает дробную часть, а округляет число. о_0 Для меня было неожиданностью.
Пример три:
Переполнение буфера отладчика поможет вам сойти с ума в процессе отладки рабочего алгоритма:
http://www.boolean.name/showthread.php?t=550
Пример 4етыре:
В ходе написания всё той же проги я столкнулся и с тем что сумма целых чисел волшебным образом преобразуется из например 6 в 5.999, если переменные, используемый в вычисленяих были float-типа.
--------------------
Я НЕ СУМАСШЕДШИЙ!
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо impersonalis за это полезное сообщение:
|
|
20.01.2007, 11:08
|
#2
|
Элита
Регистрация: 02.10.2005
Сообщений: 1,789
Написано 132 полезных сообщений (для 252 пользователей)
|
Re: Математика в Blitz3D
о последнем кажется ещё Jimon упомиинал ![:)](images/smilies/smile.gif)
|
(Offline)
|
|
20.01.2007, 13:17
|
#3
|
|
Re: Математика в Blitz3D
ага было такое
когда делиш на 0 и ошибки не выскакивает
0 магическим способом превращается в 0.00001 ![:)](images/smilies/smile.gif)
|
|
|
20.01.2007, 16:24
|
#4
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Re: Математика в Blitz3D
Сообщение от ZanoZa
о последнем кажется ещё Jimon упомиинал ![:)](images/smilies/smile.gif)
|
Ели бы я не поинтерсовался, он бы не так быстро это заметил
Так - а первый пример у всех работает неправильно?
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
23.01.2007, 02:44
|
#5
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Re: Математика в Blitz3D
Тест на С++ показал, что проблема в типе переменной. Корректно начинает работать с 8-байтовыми (double)
#include<iostream.h>
#include<conio.h>
template<class abstr>
void calc(abstr formal)
{
cout<<"===\n";
cout<<"for "<<sizeof(formal)<<" bytes"<<endl;
abstr intervalx[20];
abstr temp0,temp1,temp2,b;
short tempc;
abstr x=14.143;
abstr xmax=15.051;
abstr h=0.242;
temp0=13.417;
tempc=1;
while(temp0<=xmax){
temp2=temp0+h;
intervalx[tempc]=temp2;
temp0=temp2;
tempc++;
}
b=intervalx[3];
if(x==b)
cout<<x<<"="<<b<<endl;
else
cout<<x<<"!="<<b<<endl;
cout<<"===\n";
}
void main()
{
float x1;
double x2;
calc(x1);
calc(x2);
cout<<endl;
getch();
}
===
for 4 bytes
14.143!=14.143
===
===
for 8 bytes
14.143=14.143
===
|
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
23.01.2007, 08:56
|
#6
|
|
Re: Математика в Blitz3D
странно... надо на разных компах посмотреть
обычно double имеет привычку "плыть"
....
сорс пришлось поправить ![:)](images/smilies/smile.gif) а то там с stl трабла ![:)](images/smilies/smile.gif) компиляторы разные
но результат с тобой одинаковый
* тут че то не то ![:)](images/smilies/smile.gif)
|
|
|
23.01.2007, 13:15
|
#7
|
Дэвелопер
Регистрация: 17.01.2006
Сообщений: 1,512
Написано 78 полезных сообщений (для 110 пользователей)
|
Re: Математика в Blitz3D
Достаточно такую штуку написать:
float t1;
double t2;
t1=14.143;
t2=14.143;
if (t1==t2)
cout<<t1<<"="<<t2<<endl;
else
cout<<t1<<"!="<<t2<<endl;
Результат будет "!=". Помогло только такое сравнение
Это должно быть связано с отличием представления данных в формате float и double. От нас что-то скрывают.
Но встает вопрос, почему то же самое творится в блице, если там только float.
x=14.143
b=14.142
b=b+.001
If x=b
Print ""+x+"="+b
Else
Print ""+x+"<>"+b
EndIf
Выдает "<>". Тут, похоже, действует прикол блица представлять числа в виде 14.14300001 или 14.14299999 или что-то типа того, а при выводе нам это не показывают.
|
(Offline)
|
|
28.12.2008, 02:53
|
#8
|
Ференька
Регистрация: 26.01.2007
Адрес: улица Пушкина дом Колотушкина
Сообщений: 10,741
Написано 5,461 полезных сообщений (для 15,675 пользователей)
|
Ответ: Математика в Blitz3D
Видимо, это какой-то масонский заговор во главе с Марском Сибли... ![Wild](images/smilies/wild.gif)
__________________
Мои проекты:
Анальное Рабство
Зелёный Слоник
Дмитрий Маслов*
Различие**
Клюква**
* — в стадии разработки
** — в стадии проектирования
Для проектов в стадии проектирования приведены кодовые имена
|
(Offline)
|
|
30.12.2008, 16:22
|
#9
|
Blitz's Shame !!
Регистрация: 31.03.2007
Сообщений: 3,639
Написано 832 полезных сообщений (для 2,013 пользователей)
|
Ответ: Математика в Blitz3D
хех...
x#=14.143
b#=14.142
b#=b+0.001
If x=b
Print ""+x+"="+b
Else
Print ""+x+"<>"+b
EndIf
WaitMouse()
так неравно
x#=14.143
b#=14.142
b#=b+0.001
x = Float(Str(x))
b = Float(Str(b))
If x=b
Print ""+x+"="+b
Else
Print ""+x+"<>"+b
EndIf
WaitMouse()
а так равно !!
|
(Offline)
|
|
30.12.2008, 17:02
|
#10
|
Злобный Админ
Регистрация: 04.09.2005
Сообщений: 5,926
Написано 3,415 полезных сообщений (для 9,330 пользователей)
|
Ответ: Математика в Blitz3D
Программисты, сколько можно, ну всюду же везде в любой книге пишут что нельзя применять оператор сравнения = для переменных с плавающей точкой. Т.к. переменные с плавающей точкой имеют ограничение по точности, и 2е переменные типа float будут равны только в случае если они обе были установлены идентичными выражениями или установлены одна от другой.
Повторим ещё раз "Оператора = для переменных с плавающей запятой несуществует"
__________________
Последний раз редактировалось SBJoker, 30.12.2008 в 21:37.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
30.12.2008, 20:22
|
#11
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: Математика в Blitz3D
2 SBJoker вы сударь последнее время критикуете всё с такой яростью, что вам в пору иметь более брутальный никнейм, это во-первых. Во-вторых, что за традиция ссобщать всё пост-фактум? До последнего молчать обо всех алгоритмических изысках,а потом "бойааанЪ". В-третьих, я не встречал высказнного вами "очевидного" правила ни в одной (!) прочитанной книге. В-четвёртых это нихрена не очевидно, что функция вывода возрващает число Х, которое на саммом деле нифига не Х (при том, что функция никак не модифицирует число) и, в-пятых, совсем колдунство - пропускание флоат-а через String type cast. В-шестых:
переменные с плавающей точкой имеют ограничение по точности, и 2е переменые типа флоат будут равны только в случае если они обе были установлены идентичными выражениями или установлены одна от другой.
|
Вы понимаете - в примере не использованы связки деление-умножение (приводящие к потери точности из-за апроксимации бесконечнй дроби конечной мантиссой), вовлечённые в операции константы и результаты операций далеки от переполнения формата - т.е. ещё раз "нихрена не очевидно".
В-седьмых: концепт "Злобный Модератор" вырождается в концепт "Злобный дед", такие люди читают орфографическое правило с примером неверного написания слова, и забыв про контекст, черкают ручкой ошибочное место. Попутно послыая и автора и отсальных читателей.
2 IGR и? ты повторил кусок моей заметки с моим выводом - и что?
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
30.12.2008, 21:52
|
#12
|
Злобный Админ
Регистрация: 04.09.2005
Сообщений: 5,926
Написано 3,415 полезных сообщений (для 9,330 пользователей)
|
Ответ: Математика в Blitz3D
Сообщение от impersonalis
2SBJoker вы сударь последнее время критикуете всё с такой яростью, что вам в пору иметь более брутальный никнейм, это во-первых.
|
Вы меня ни с кем не путаете? Я вообще крайне редко пишу в форум без веских причин.
Сообщение от impersonalis
Во-вторых, что за традиция ссобщать всё пост-фактум? До последнего молчать обо всех алгоритмических изысках,а потом "бойааанЪ".
|
В мои обязаности не входит учить форумчан основам программирования, считается что базовые правила знают все.
Сообщение от impersonalis
В-третьих, я не встречал высказнного вами "очевидного" правила ни в одной (!) прочитанной книге.
|
М.б. вы читали не те книги или не так подробно. Или просто пропустили раздел "для самых маленьких" как тот в котором Вам давно всё извесно.
Вот пример:
"Избегайте сравнений на равенство. Числа с плавающей запятой, которые должны быть равны, на самомо деле равны невсегда. Главная проблема в том, что два разных способа получить одно и тоже число не всегда приводит к одинаковому результату."
"Совершенный код", С.Макконелл, издательства Microsoft, Питер, Русская редакция/ стр.286, последний абзац.
Всем очень рекомендую почитать эту книгу, даже самые самоувереные гуру-программисты найдут много полезного и то чего они сами незнали.
Сообщение от impersonalis
В-четвёртых это нихрена не очевидно, что функция вывода возрващает число Х, которое на саммом деле нифига не Х (при том, что функция никак не модифицирует число) и, в-пятых, совсем колдунство - пропускание флоат-а через String type cast. В-шестых:
Вы понимаете - в примере не использованы связки деление-умножение (приводящие к потери точности из-за апроксимации бесконечнй дроби конечной мантиссой), вовлечённые в операции константы и результаты операций далеки от переполнения формата - т.е. ещё раз "нихрена не очевидно".
|
Любая, я подчёркиваю любая операция с вещественными цислами запускает махенизм перекомпоновки числа в отведёную ему память. Это неизбежно приводит к округлению последнего знака.
Сообщение от impersonalis
В-седьмых: концепт "Злобный Модератор" вырождается в концепт "Злобный дед", такие люди читают орфографическое правило с примером неверного написания слова, и забыв про контекст, черкают ручкой ошибочное место. Попутно послыая и автора и отсальных читателей.
|
Спасибо за оценку.
__________________
|
(Offline)
|
|
Эти 3 пользователя(ей) сказали Спасибо SBJoker за это полезное сообщение:
|
|
13.01.2009, 12:00
|
#13
|
Злобный Админ
Регистрация: 04.09.2005
Сообщений: 5,926
Написано 3,415 полезных сообщений (для 9,330 пользователей)
|
Ответ: Математика в Blitz3D
Вот специально решил выложить инфу из MSDN по типам переменных, это актуально и для встроенных типов Blitz3D:
float:
Примерные приделы значений: от ±1.5 * 10^-45 до ±3.4 * 10^38 (крайние приделы по сути не имеют дробной или целой части.)
Точность: 7 цифр (т.е. в числе без потери точности может быть не более 7 цифр в сумме из целой и дробной частей.)
|
Что из этого следует? В любом языке 32х битный float ограничен 7 цифрами в числе. Т.е. если мы хотим работать с точностью до 3его знака в дробной части, то целая часть недолжна превышать 4 знаков или числа 9999 (на самом деле число может быть чуть больше из-за несоответствий между десятичной и двоичной системами счисления). Если мы хотим работать с числами в целой части которых 7 знаков, то можно забыть о дробной чатси совсем. Её просто небудет.
А теперь о несуществующем в Blitz3D типе double, которых бы всех спас.
double
Примерные приделы значений: от ±5.0 * 10^-324 до ±1.7 * 10^308 (крайние приделы по сути не имеют дробной или целой части.)
Точность: 15-16 цифр (т.е. в числе без потери точности может быть не более 15 (иногда 16, когда первая цифра "1") цифр в сумме из целой и дробной частей.)
|
Как мы видим уже можно использовать числа имеющие длину до 15-16 символов в строковом представлении... т.е. всреднем до 8 цифр до и после запятой.
напомню типа double нет в BlitzD, но он есть в BlitzMAX, C#, C++
__________________
Последний раз редактировалось SBJoker, 13.01.2009 в 12:13.
|
(Offline)
|
|
13.01.2009, 12:31
|
#14
|
Дэвелопер
Регистрация: 10.09.2007
Сообщений: 1,442
Написано 793 полезных сообщений (для 1,460 пользователей)
|
Ответ: Математика в Blitz3D
SBJoker
молодец, правильно все объяснил.
добавлю вот что:
стек FPU 80битный, float 32бита, double - 64.
пока вычисления происходят без сохранения в память из стека FPU - точность 80битная (это правда зависит от флагов FPU). как только сохраняем значение в переменную - происходит отсечение (SBjoker об этом и сказал).
также стоит знать про машинный эпсилон (наименьшее представимое число с заданной разрядной сеткой). еще надо помнить, что формат IEEE 754 предусматривает повышение точности в области чисел в диапазоне 0..1 (хотя память мне тут может изменять, смотрите номрализованную и денормализованную форму числе с плавающей точкой).
так что не пугайтесь, когда видите, что 10.0 показывается как 9,999999. все так и зажумано ![:)](images/smilies/smile.gif)
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо ffinder за это полезное сообщение:
|
|
13.01.2009, 12:41
|
#15
|
Blitz's Shame !!
Регистрация: 31.03.2007
Сообщений: 3,639
Написано 832 полезных сообщений (для 2,013 пользователей)
|
Ответ: Математика в Blitz3D
impersonalis, сорри, очень бистро просмотрел пост - неувидел !!
SBJoker, спасибо за книгу !!
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:57.
|