Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: Padding with sprintf changing number

by haukex (Bishop)
on Sep 24, 2021 at 11:35 UTC ( #11136987=note: print w/replies, xml ) Need Help??


in reply to Padding with sprintf changing number

The number stored in $amount is likely to be something like 488714.9999999999 instead of 488715, and since Perl is unlikely to simply upconvert an integer of that size to a floating-point number on its own, it's likely that you're doing some kind of floating-point operations on the number that you haven't shown us. See What Every Programmer Should Know About Floating-Point Arithmetic.

The Perl Cookbook says "When Perl is told to print a floating-point number but not told the precision, it automatically rounds that number to however many decimal digits of precision that your machine supports." If you don't mind the performance hit, you could use bignum for precise calculations. If you don't mind the imprecision (which would not be advisable if this "amount" has anything to do with money), you could use the %016.0f as suggested by choroba. (Update: If all of the calculations you're doing deal only with integers, and in particular if you're ok with integer division, you could also consider integer. Update 2: The reply indicates that this is not an option in this case.)

Replies are listed 'Best First'.
Re^2: Padding with sprintf changing number
by sachin raj aryan (Acolyte) on Sep 24, 2021 at 11:37 UTC

    This was the operation i was doing it before padding

    print " Checking amnt before conversion $amt,\n"; $amt= sprintf("%.2f",$amt); print " Checking amnt after rounding $amt,\n"; $amt = $amt*100;

      4887.15 cannot be stored accurately as a floating-point number, which is may be is causing your issue. See my post above for more information.

        4887.15 cannot be stored accurately as a floating-point number, which is causing your issue.

        Could it be that (at least part of) the problem is that the OP is expecting that sprint("%d", 488714.999) will return the string 488715 ?
        It won't:
        C:\>perl -le "print sprintf('%d', 488714.999);" 488714

        Cheers,
        Rob
Re^2: Padding with sprintf changing number
by sachin raj aryan (Acolyte) on Sep 27, 2021 at 12:29 UTC

    I am not sure how things changed please see my output 1348 4887.15 -----> this is the line i copy pasted no operation Checking amnt before conversion 4887.15, Checking amnt after rounding 4887.15, Checking amnt after conversion 488715, 488714 i m checking amount before padding, 0000000000488714 i m checking amount after padding, why it

    print " Checking amnt before conversion $amt,\n"; $amt= sprintf("%.2f",$amt); print " Checking amnt after rounding $amt,\n"; $amt = $amt*100; print " Checking amnt after conversion $amt,\n"; sub amnt($amn) { my $amount=$_[0]; $amount=int($amount); say "$amount i m checking amount before padding,\n"; #my $padamnt = sprintf("%016.0f",$amount);---> currently commented to +check integer effect. my $padamnt = sprintf("%016d",$amount); say "$padamnt i m checking amount after padding,\n"; return $padamnt; }
      I've rewritten your code into a form that I think makes at least some sense:
      use strict; use warnings; my $amt = 4887.15; print " Checking amnt before conversion $amt,\n"; $amt= sprintf("%.2f",$amt); print " Checking amnt after rounding $amt,\n"; $amt = $amt*100; print " Checking amnt after conversion $amt,\n"; printf "Checking the EXACT value of amnt: %.17g\n", $amt; amnt($amt); sub amnt { my $amount=$_[0]; $amount=int($amount); print "$amount i m checking amount before padding,\n"; #my $padamnt = sprintf("%016.0f",$amount);---> currently commented to +check integer effect. my $padamnt = sprintf("%016d",$amount); print "$padamnt i m checking amount after padding,\n"; return $padamnt; }
      When I run that script, I get:
      Checking amnt before conversion 4887.15, Checking amnt after rounding 4887.15, Checking amnt after conversion 488715, Checking the EXACT value of amnt: 488714.99999999994 488714 i m checking amount before padding, 0000000000488714 i m checking amount after padding,
      Note that I've added a line of code that demonstrates that the EXACT value of $amt is NOT 488715.
      Perl's print() function frequently fails to produce an accurate representation of floating point values - and that's what is happening here.

      That output I'm seeing is as I expect.
      Which is the line of output that you don't understand ?

      You need to stay alert to this aspect of perl's print() function.
      Neither python3 nor raku are afflicted with such a poorly designed implementation:
      $ python3 -c "print(4887.15 * 100)" 488714.99999999994 $ raku -e "say 4887.15e0 * 100" 488714.99999999994


      Cheers,
      Rob
        > Neither python3 nor raku

        But

        $ python2 -c 'print(4887.15 * 100)' 488715.0

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11136987]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (3)
As of 2022-05-21 07:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (76 votes). Check out past polls.

    Notices?