use warnings; use strict; use POSIX qw/round/; use Test::More tests => 2; # somebody used a generating algorithm that used 32-bit single-precision floats, entered 1.13, but thought it was double-procision so printed it into your database as %.15f; so now your api returns '1.129999995231628' for a number intended to be exactly 1.13 # 1.12999999523162841796875 # exact 32-bit float representation of 1.13 sub get_from_api { '1.129999995231628' } # sprintf '%.15f', 1.12999999523162841796875; my $from_api = get_from_api(); print "string from_api = '$from_api' straight from api\n"; $from_api .= '.' unless $from_api =~ /\./; $from_api .= '00'; $from_api =~ s,^(\d+)\.(\d{2}).*$,${1}${2},; print "string from_api = '$from_api' after text manipulation\n"; $from_api += 0; print "bad rounding = ", $from_api, "cents\n"; is $from_api, 113, "should be 113 cents"; #### redo, with proper rounding $from_api = get_from_api(); print "string from_api = '$from_api' straight from api\n"; $from_api .= '.' unless $from_api =~ /\./; $from_api .= '00'; $from_api =~ s,^(\d+)\.(\d{2})(\d*).*$,${1}${2}.${3},; print "string from_api = '$from_api' after text manipulation\n"; $from_api = round($from_api); print "good rounding = ", $from_api, "cents\n"; is $from_api, 113, "should be 113 cents";