Вверх ↑
Этот топик читают: Гость
Ответов: 1297
Рейтинг: 47
#1: 2015-12-16 00:20:54 ЛС | профиль | цитата
Привет всем! Помогите побороть, никак не могу понять, как 1.2 может быть меньше 1.2 когда они по всей видимости равны. А по схеме так и выходит... Чудеса, или с головой что-то?)) Спасибо.
Когда-то судя по поиску поднимал такую тему, но тогда проблема была явная, а сейчас непонятно..
http://forum.hiasm.net/forum.html?q=3&p=252963

Придется писать свой If-Else на IC ?))
Эх, а я надеялся на Хиасм бортовой компьютер пилотируемой космической станции и ядерные боеголовки точного наведения для ядерного щита программировать))



code_36649.txt
карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
файлы: 1code_36649.txt [900B] [597]
Разработчик
Ответов: 26267
Рейтинг: 2141
#2: 2015-12-16 02:13:21 ЛС | профиль | цитата
Что-то из этой оперы -- http://forum.hiasm.net/forum.html?q=3&p=280687#p280687

Для решения проблемы можно применить округление

Add(MainForm,2953706,350,182)
{
}
Add(Math,10257649,413,259)
{
Op2=0.1
Default=1
link(onResult,4019485:doOperation,[])
link(Op1,10257649:Result,[(419,250)(399,250)(399,301)(419,301)])
}
Add(Timer,3635841,350,259)
{
Interval=500
link(onTimer,10257649:doOperation,[])
}
Add(If_else,14492764,525,259)
{
Type=1
link(onTrue,9748858:doString,[])
link(Op1,9020621:Var2,[])
}
Add(FormatStr,9748858,581,259)
{
Mask="%1 < %2"
link(onFString,5250440:doMessage,[])
link(Str1,9020621:Var3,[(587,233)])
}
Add(Message,5250440,630,259)
{
}
Add(Memory,1566946,525,182)
{
@Hint=#15:Current Version|
Default=Real(1.2)
}
Add(GetDataEx,9020621,525,228)
{
link(Data,1566946:Value,[])
}
Add(Math,4019485,469,259)
{
OpType=35
Op2=0.01
link(onResult,14492764:doCompare,[])
}

карма: 22

0
Ответов: 1297
Рейтинг: 47
#3: 2015-12-16 02:38:37 ЛС | профиль | цитата
Спасибо Неско, завтра проверю. Сейчас на айпаде. Но если виновато округление, тогда почему число 1.1 не вызывает срабатывания? Такое ощущение что оператор выполняется не меньше, а меньше или равно. Странновато.
карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
Разработчик
Ответов: 26267
Рейтинг: 2141
#4: 2015-12-16 02:53:17 ЛС | профиль | цитата
Aziz писал(а):
Такое ощущение что оператор выполняется не меньше, а меньше или равно.

Нормальное обычное сравнение идет

      data_real:
begin
r := ToReal(op2);
case OpType of
0: Result := op1.rdata = r;
1: Result := op1.rdata < r;
2: Result := op1.rdata > r;
3: Result := op1.rdata <= r;
4: Result := op1.rdata >= r;
5: Result := op1.rdata <> r;
end;
end;
карма: 22

0
Ответов: 8947
Рейтинг: 824
#5: 2015-12-16 10:00:08 ЛС | профиль | цитата
Aziz, тут и проверять нечего, знать надо что компьютер пользует двоичную систему, а не десятичную и дроби круглые в десятичной в двоичной системе периодические и бесконечны в большинстве случаев, в т. ч. и 0.1 и 0.2:
0.1[10]=0.000110011001100110011001100....[2]
0.2[10]=0.001100110011001100110011001....[2]
В зависимости от того на какую цифру "1" или "0" пришлось округление последнего знака (для Real 8-байтного числа это 52-ой бит после запятой) округление будет с избытком или недостатком, вот и получается, что 0.1+0.1<>0.2.
А в какую сторону не равно, можете сами проверить продолжив дроби до 52 знака, округлив их до 51 знаков и сложив 0.1 + 0.1 и сравнивая сумму с 0.2
карма: 19

0
Ответов: 1297
Рейтинг: 47
#6: 2015-12-16 10:12:08 ЛС | профиль | цитата
Любопытные грабли) Спасибо!
------------ Дoбавленo в 09.35:
Такое ощущение, что я вернулся в эпоху аналоговых вычислительных машин, когда число определяется неоднозначно. В принципе, тип Real - это и есть аналог, и его действительно точно никогда не вычислишь. Все-таки мир не оцифруешь никак( Хотя есть мнение что само Бытие имеет дискретную природу, и что аналог - лишь высококачественная выборка с квантованием на уровне кварков)
------------ Дoбавленo в 09.36:
Может, раз так, стоит встроить это округление в элементы? Во избежание неуловимых глюков.
карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
Разработчик
Ответов: 26267
Рейтинг: 2141
#7: 2015-12-16 11:50:37 ЛС | профиль | цитата
Aziz писал(а):
Может, раз так, стоит встроить это округление в элементы?

Не стоит. Иногда количество разрядов округления является значением неопределенным
карма: 22

0
Ответов: 1297
Рейтинг: 47
#8: 2015-12-16 13:16:52 ЛС | профиль | цитата
Я имел ввиду, с полем для указания количества разрядов округления конечно. Или тогда встроить в справку этот пример)
------------ Дoбавленo в 12.09:
Спасибо, Неско, все заработало. Буду теперь аккуратнее с дробными числами.
------------ Дoбавленo в 12.12:
Писал модуль для автоматической проверки обновлений программы на сервере, где перебирал номера версий и подставлял в имя файла, если есть такого размера файл на сервере с максимальной версией, значит обновление есть. А то раньше закачивал спец. текстовый файлик с версией и проверял и правил его.
------------ Дoбавленo в 12.36:
Вот, тут схожая проблема описана и ответ на нее.

http://www.sql.ru/forum/423601/drobnye-chisla-16-16-ne-vypolnyaetsya

i := i + 0.1;
- по моему, один из первых примеров особеностей двоичного представления, это то, что числа вида 0.1 в двоичном виде представляют из себя бесконечную периодичную дробь. то есть, не могут быть представлены точно

------------ Дoбавленo в 12.41:
Значит все дело именно в "опасном" числе 0.1. Потому что если его заменить на 0.2 то все работает без округления. HiAsm, теперь я готов с тобой лететь в черные дыры Космоса!)

Add(MainForm,2953706,21,105)
{
@Hint=#45:http://forum.hiasm.net/forum.html?q=3&t=65565|
}
Add(Math,10257649,476,154)
{
Op2=0.2
Default=1
link(onResult,14492764:doCompare,[])
link(Op1,12277268:Var1,[(482,142)(470,142)(470,198)])
}
Add(Timer,3635841,357,154)
{
Interval=500
link(onTimer,10257649:doOperation,[])
}
Add(If_else,14492764,581,154)
{
Type=2
link(onTrue,9748858:doString,[])
link(Op2,2700034:Var3,[(594,135)])
}
Add(FormatStr,9748858,672,154)
{
Mask="%1 < %2"
link(onFString,5250440:doMessage,[])
link(Str1,2700034:Var2,[(678,143)(531,143)])
link(Str2,12277268:Var3,[(685,142)(475,142)])
}
Add(Message,5250440,784,154)
{
}
Add(Memory,1566946,252,147)
{
@Hint=#15:Current Version|
Default=Real(1.4)
}
Add(Math,4019485,525,287)
{
OpType=35
Op2=0.01
}
Add(GetDataEx,2700034,525,130)
{
Angle=3
link(Data,1566946:Value,[(426,135)(426,191)(258,191)])
}
Add(GetDataEx,12277268,469,193)
{
Angle=1
link(Data,10257649:Result,[(482,198)])
}


карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
Ответов: 8947
Рейтинг: 824
#9: 2015-12-16 14:04:12 ЛС | профиль | цитата
Aziz писал(а):
дело именно в "опасном" числе 0.1
Полагаю, что дело в голове программиста
карма: 19

0
Ответов: 1297
Рейтинг: 47
#10: 2015-12-16 21:21:20 ЛС | профиль | цитата
Неужели все так плохо) Голова ни при чем, она либо глючит, либо учится)) Моя вроде научилась) Отсутствие знания этой специфики обработки и представления чисел - это уже прикладной аспект, вернее даже ограничения и несовершенства вычислительных инструментов..
карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
Ответов: 8947
Рейтинг: 824
#11: 2015-12-16 22:58:55 ЛС | профиль | цитата
Леонид писал(а):
..можете сами проверить продолжив дроби..
Вы этого не сделали, и не отписались: "А-а, вот оно что! Теперь понятно!". А навесили ярлык на "0.1"
карма: 19

0
Ответов: 1297
Рейтинг: 47
#12: 2015-12-16 23:38:54 ЛС | профиль | цитата
Да, признаюсь, не было времени вникать в двоичный код.. Но тем не менее провел эксперимент - только с 0.1 происходит глюк. Ставил и 0.2 и 0.3 - все путем. И потом коллеги по ссылке выше уже подтвердили особый статус этого числа. Это ускользающе малая величина или сравнимая с шумами погрешностей округления.. Я практик, мне пока этого достаточно..))
карма: 3
Hiasm + Flowstone + CopperCube + GoDot + JS
0
12
Сообщение
...
Прикрепленные файлы
(файлы не залиты)