Как мне исправить этот код Perl, чтобы 1.1 + 2.2 == 3.3?

Как мне исправить этот код, чтобы 1.1 + 2.2 == 3.3? Что на самом деле здесь происходит, что вызывает такое поведение? Я смутно знаком с задачами округления и математикой с плавающей запятой, но я думал, что это применимо только к делению и умножению и будет видно в выводе.

[me@unixbox1:~/perltests]> cat testmathsimple.pl 
#!/usr/bin/perl

use strict;
use warnings;

check_math(1, 2, 3);
check_math(1.1, 2.2, 3.3);

sub check_math {
        my $one = shift;
        my $two = shift;
        my $three = shift;

        if ($one + $two == $three) {
                print "$one + $two == $three\n";
        } else {
                print "$one + $two != $three\n";
        }
}

[me@unixbox1:~/perltests]> perl testmathsimple.pl 
1 + 2 == 3
1.1 + 2.2 != 3.3

Изменить:

Большинство ответов на данный момент соответствуют строкам "это проблема с плавающей запятой, да" и предлагают обходные пути для ее решения. Я уже подозреваю, что в этом проблема. Как мне это продемонстрировать? Как заставить Perl выводить переменные в длинной форме? Сохранение вычисления $ one + $ two в переменной temp и его печать не демонстрируют проблему.

Edit:

Используя технику sprintf, продемонстрированную aschepler, теперь я могу «увидеть» проблему. Кроме того, использование bignum, рекомендованное mscha и rafl, решает проблему несоответствия сравнения. Однако вывод sprintf по-прежнему указывает, что числа не "правильные". Это оставляет небольшое сомнение в этом решении.

Является ли bignum хорошим способом решить эту проблему? Есть ли какие-либо возможные побочные эффекты bignum, на которые мы должны обратить внимание при интеграции его в более крупный существующий, программа?

9
задан brian d foy 14 October 2010 в 18:40
поделиться