Come posso risolvere questo codice in modo che 1.1 + 2.2 == 3.3? Cosa sta realmente accadendo qui che sta causando questo comportamento? Ho vagamente familiarità con problemi di arrotondamento e matematica in virgola mobile, ma ho pensato che fosse applicato solo alla divisione e alla moltiplicazione e sarebbe visibile nell'output.Come posso correggere questo codice Perl in modo che 1.1 + 2.2 == 3.3?
[[email protected]:~/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";
}
}
[[email protected]:~/perltests]> perl testmathsimple.pl
1 + 2 == 3
1.1 + 2.2 != 3.3
Edit:
maggior parte delle risposte finora sono sulla falsariga di "si tratta di un problema in virgola mobile, duh" e stanno fornendo soluzioni per esso. Ho già il sospetto che questo sia il problema. Come lo dimostro? Come ottengo Perl per produrre la forma lunga delle variabili? Memorizzare il $ 1 + $ due di calcolo in una variabile temporanea e stamparlo non dimostra il problema.
Edit:
Utilizzando la tecnica sprintf dimostrata da aschepler, io sono ora in grado di "vedere" il problema. Inoltre, l'utilizzo di bignum, come raccomandato da mscha e rafl, risolve il problema del confronto non essendo uguale. Tuttavia, l'output di sprint indica ancora che i numeri non sono "corretti". Questo lascia un minimo di dubbio su questa soluzione.
Bignum è un buon modo per risolvere questo problema? Ci sono alcuni possibili effetti collaterali di bignum che dovremmo considerare quando li integriamo in un programma più grande ed esistente?
Ahh, OK. Bene, puoi farlo: stampa "$ uno + $ due! = $ Tre \ n"; stampa ($ tre - ($ uno + $ due)). "\ N"; e vedrai qualcosa del tipo: "1.1 + 2.2! = 3.3 \ n-4.44089209850063e-16 \ n". Quindi puoi manipolare le stringhe per metterle insieme in una variabile. –
Stampa '$ uno + $ due - $ tre' per dimostrarlo. 'perl -e '$ one = 1.1; $ two = 2.2; $ three = 3.3; print $ one + $ two- $ three' ==> 4.44089209850063e-16' YMMV. – mob
Se vuoi usare 'bignum', usa un metodo di' Math :: BigFloat', non 'sprintf'. Ad esempio, 'stampa $ num-> bstr();'. Passare un numero a 'sprintf' probabilmente lo converte in un normale numero a virgola mobile (' double') prima di convertirlo in stringa. – aschepler