Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Сравнение одинаковых чисел возвращает false


Автор: Pfailed 19.7.2009, 10:21
Здравствуйте.
Я столкнулся сегодня с очень удивительной для меня вещью. При сравнении, казалось бы, двух одинаковых чисел я получаю результат что эти числа не равны.
Я что то упустил при изучении Perl? Баг это или фича?
perl --version
Цитата

This is perl, v5.10.0 built for x86_64-linux-gnu-thread-multi


Код вызывающий аномалии:
Код

my ($i, $j) = (0, 1);
for(1..25)
{
    $i += 0.04;
}
print ($i == $j ? "$i==$j\n" : "$i!=$j\n");


Результат выполнения этого кода:
Цитата

1!=1

Подскажите пожалуйста.

Автор: kavkaz 19.7.2009, 10:34
ввиду погрешностей в  $i не значение 1, а 1.0000001

нужно округлить.

Автор: Pfailed 19.7.2009, 11:00
Спасибо за разъяснение.
Чувствую что, я что-то упустил в этой жизни smile  Просто не подозревал, что при сложении малых чисел могут образовываться погрешности.
Еще смущает, что print выводит 1 хотя честнее было бы в таком случаи вывести 1.0000001

Автор: Logo 19.7.2009, 11:15
Вот статья, поможет разъяснить. http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374&mode=print
Если коротко - в двоичной системе в виде конечной дроби можно представить только дроби, знаменатель, разложенный на простые множители, представляет только двойки. А в десятичной если простые множители знаменателя состоят из двоек и пятерок (2*5=10).
Но, к примеру, если в знаменателе есть тройка, получится что-то вроде 0.33333... - бесконечная дробь, с периодом (3). Также в двоичной системе нельзя представить 1/25 конечной дробью. Поскольку числа в памяти хранятся в двоичной системе, конечной дроби, часть числа и теряется.

Автор: DaemonSuw 19.7.2009, 20:34
Код

use Math::BigFloat;
my $i = Math::BigFloat->new(0);
my $j = Math::BigFloat->new(1);
$i += 0.04 for (1..25);
print ($i == $j ? "$i==$j\n" : "$i!=$j\n");


http://search.cpan.org/~tels/Math-BigInt-1.89/lib/Math/BigFloat.pm

Цитата

C:\>test_big_float.pl
1==1

Автор: kavkaz 20.7.2009, 08:36
Цитата(Pfailed @  19.7.2009,  11:00 Найти цитируемый пост)
Еще смущает, что print выводит 1 хотя честнее было бы в таком случаи вывести 1.0000001 



Код

printf("%.8f", $i);

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)