With this line, I expect the output 201
$ perl -e '$e = '2.01'; $c = sprintf("%d", $e * 100); print $c;'
But I get 200
instead. I don't understand why.
With this line, I expect the output 201
$ perl -e '$e = '2.01'; $c = sprintf("%d", $e * 100); print $c;'
But I get 200
instead. I don't understand why.
Because of the binary representation of a float number.
Try:
perl -e '$e = 2.01;printf("%2.25f\n",$e);'
Output:
2.0099999999999997868371793
The intetger part of this number multiplied by 100 gives 200
perl -e 'my $e = "2.01"; my $c = sprintf("%.0f", $e * 100); print $c;'
With %d
, the integer is truncated.
And if you don't bother with printf
:
perl -e 'my $e = "2.01"; my $c = $e * 100; print $c;'
Floating point representation has a limit to its accuracy, and the binary representation of 2.01
just happens to be fractionally less than 2.01.
The %d
format conversion truncates the value to the next lowest value. It actually does a call to int
, whose documentation says
You should not use this function for rounding: one because it truncates towards 0 , and two because machine representations of floating-point numbers can sometimes produce counterintuitive results.
And int(200.99999999999)
is 200, which is what you are getting.
The canonical way in Perl to get the closest integer to a floating point value is to use the %f
conversion with zero decimal points. So if you write instead
perl -e '$e = '2.01'; $c = sprintf("%.0f", $e * 100); print $c;'
you will get the output
200
Following document mentions about floating point and binary representation. This is from python.org, but it also works for perl.
https://docs.python.org/3/tutorial/floatingpoint.html
$ perl -e 'if (2.01 + 2.01 + 2.01 == 6.03) { print "yes" } else { print "no" }'
no
You can try using bignum
pragma as a makeshift:
$ perl -Mbignum -e '$e = "2.01"; $c = sprintf("%d", $e * 100); print $c;'
201