Что нового

Некорректная работа с Float числами

timsky

Осваивающий
Сообщения
93
Репутация
28
Сколько будет 251.187 - 247.015? У меня выдает 4.17200000000003 :shok:
На днях столкнулся с этим багом и помогло только принудительное округление :wacko:
Пробовал на Win XP SP3 и Win 7 x64 / AutoIt 3.3.6.1. Вот пример:

Код:
$in = Number('247.015')
$out = Number('141.796')
$in2 = Number('251.187')
$out2 = Number('142.373')
MsgBox(0, IsNumber($in) & IsFloat($in) & IsInt($in) & IsString($in), $in - $in2 & @CRLF & $out - $out2)

$in = 247.015
$out = 141.796
$in2 = 251.187
$out2 = 142.373
MsgBox(0, IsNumber($in) & IsFloat($in) & IsInt($in) & IsString($in), $in - $in2 & @CRLF & $out - $out2)

$in = '247.015'
$out = '141.796'
$in2 = '251.187'
$out2 = '142.373'
MsgBox(0, IsNumber($in) & IsFloat($in) & IsInt($in) & IsString($in), Round($in - $in2, 3) & @CRLF & Round($out - $out2, 3))


Или я чего-то не догоняю?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 401
timsky [?]
Сколько будет 251.187 - 247.015? У меня выдает 4.17200000000003
А сколько ты ожидаешь?
Калькулятор выдаёт то же число.

Вот проверь с обратным действием:

Код:
$Num1 = 251.187
$Num2 = 247.015

$iCalc = ($Num1 - $Num2)
$iCalcBack = $iCalc + $Num2

ConsoleWrite($iCalc & @LF)
ConsoleWrite($iCalcBack & @LF)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
CreatoR [?]
Калькулятор выдаёт то же число.
У меня калькулятор (и calc.exe, и Calculator.exe от от Yashied, и внешний) выдает 4.172 :smile:
timsky
У меня тоже только так считает:
Код:
$ix_1 = 251.187
$ix_2 = 250.187867
If IsFloat($ix_1) Or IsFloat($ix_2) Then
	$iRound_1 = StringLen($ix_1) - StringInStr($ix_1, '.')
	$iRound_2 = StringLen($ix_2) - StringInStr($ix_2, '.')

	If $iRound_2 <= $iRound_1 Then
		$iRound = $iRound_1
	Else
		$iRound = $iRound_2
	EndIf
	MsgBox(0, '1', Round($ix_2 - $ix_1, $iRound))
Else
	MsgBox(0, '2', $ix_2 - $ix_1)
EndIf
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 401
madmasles [?]
У меня калькулятор выдает 4.172
И у меня, он просто округляет число.

Тогда почему сложение обратно даёт нормальный результат?
 

SyDr

Сидра
Сообщения
651
Репутация
158
http://autoit-script.ru/index.php/topic,1119.msg8148.html#msg8148

Это уже обсуждалось. Число вещественных чисел на любом промежутке бесконечно. Но в памяти компьютера можно представить только огрниченной число таких чисел.

"Баг" проявляется не всегда потому, что AutoIt пытается окрглять такие ошибки. Но, похоже, у него это не всегда получается.
 
Автор
timsky

timsky

Осваивающий
Сообщения
93
Репутация
28
CreatoR сказал(а):
timsky [?]
Сколько будет 251.187 - 247.015? У меня выдает 4.17200000000003
А сколько ты ожидаешь?
Калькулятор выдаёт то же число.

Вот проверь с обратным действием:

Код:
$Num1 = 251.187
$Num2 = 247.015

$iCalc = ($Num1 - $Num2)
$iCalcBack = $iCalc + $Num2

ConsoleWrite($iCalc & @LF)
ConsoleWrite($iCalcBack & @LF)
Ну значит неправильный калькулятор :smile: Хотя у меня на 7-ке он выдает 4.172. Это можно и в уме посчитать и такое длинное число по любому не получится.
ИМХО конкретный баг.
 

SyDr

Сидра
Сообщения
651
Репутация
158
Да поймите же вы, что числа в компе хранятся не 10-ичной системе счисления, а в 2-ичной.
 
Автор
timsky

timsky

Осваивающий
Сообщения
93
Репутация
28
Я это прекрасно понимаю, но в АвтоИт все переменные хранятся как Variant и он автоматом их преобразует при определенных операциях:
In AutoIt there is only one datatype called a Variant. A variant can contain numeric or string data and decides how to use the data depending on the situation it is being used in.
Т.е. сабж уже проделывает определенные манипуляции за кодера и я ожидал, что с этой примитивной задачей он справится.
ИМХО нужно либо внедрить ф-ю _Precise в ядро, либо указать, что далеко не всегда преобразования происходят идеально и дать примеры в справке.

Но и с _Precise не все так радужно, т.к. не всегде помогает округление до 15-ти символов. Пример:
Код:
$in = 247.015
$out = 141.796
$in2 = 251.187
$out2 = 142.373
$res1 = $in - $in2
$res2 = $out - $out2
MsgBox(0, '', 'Round 15: ' & @CRLF & Round(($res1), 15) & @CRLF & Round(($res2), 15) & @CRLF & @CRLF & 'Round 14: ' & @CRLF & Round(($res1), 14) & @CRLF & Round(($res2), 14) & @CRLF & @CRLF & 'Round 13: ' & @CRLF & Round(($res1), 13) & @CRLF & Round(($res2), 13))
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Верх