Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Fellow Monks: In a nutshell, I want to truncate a number, in this case a decimal to 3 places to the right, and not round it.
This is the small piece of code:
#!/usr/bin/perl -w use strict; my $n=34.57889; my $na=sprintf("%3.3f",$n); print "$n $na\n"; OUTPUT: 34.57889 34.579
What I want is a simple truncation of the number which would result in 34.578, not 34.579 .
Any help that you can provide in this matter would be greatly appreciated! Thank you in advance.

Replies are listed 'Best First'.
Re: Want to Truncate A Number... NOT round it
by liz (Monsignor) on Feb 11, 2004 at 20:29 UTC
    Maybe something like:
    my $n=34.57889; my $na=substr($n,0,index($n,'.') + 1 + 3); print "$n $na\n"; __END__ 34.57889 34.578

    Note the "3" is for the number of digits after the decimal "." you want to display.

    Liz

      Most Righteous! Exactly what I was looking for ! Thanks!
      Just wanted to let you know that I found this really useful. 10 years late alright!
Re: Want to Truncate A Number... NOT round it
by halley (Prior) on Feb 11, 2004 at 20:28 UTC
    The int() routine will truncate to an integer value, "toward zero." So int( $x * 100 ) / 100 will truncate to the penny.
    my $n = 34.57889; my $na = int($n * 1000) / 1000; print "$n $na\n"; __OUTPUT__ 34.57889 34.578

    A slower but interesting alternative approach... if you're dealing with long strings of digits, is to render the number to MORE digits than required, then strip the undesired digits.

    my $n = 34.57889; my $na = sprintf("%3.4f", $n); $na =~ s/(?<=\.\d\d\d)\d*$//; print "$n $na\n"; __OUTPUT__ 34.57889 34.578

    Take care when you're talking about "truncate", "floor", "ceiling" and "rounding" when you deal with negative numbers... make sure you're defining your problem correctly, too.

    --
    [ e d @ h a l l e y . c c ]

      Wouldn't
      $na =~ s/(?<=\.\d\d\d)\d*$//;
      be done better and clearer as:
      chop $na;
      ?

      Liz

      Update:
      Since the 4 digits are guaranteed by the sprintf, there should be no problem in using chop().

        Only if you're guaranteed to have exactly one digit after the desired three.

        Update in response to someone else's update: Aliens must have inserted that sprintf when I wasn't looking.

Re: Want to Truncate A Number... NOT round it
by metadoktor (Hermit) on Feb 11, 2004 at 20:34 UTC
    #!/usr/local/bin/perl -w use strict; my $n = 34.57889; my $d = 4; # Num of right hand digits to grab my ($lhs,$rhs) = split /\./,sprintf("%f",$n),2; $n = join '.',$lhs,substr($rhs,0,$d); print "$n\n";

    metadoktor

    "The doktor is in."

Re: Want to Truncate A Number... NOT round it
by CountZero (Bishop) on Feb 11, 2004 at 20:53 UTC
    TMTOWTDI:

    my $n=34.57889; $n=~/(-?\d+\.\d{3})/; print "$n - $1\n";

    Update: Added -? to the regex to handle negative numbers (thanks halley)

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      Breaks on negative numbers.

      --
      [ e d @ h a l l e y . c c ]

Re: Want to Truncate A Number... NOT round it
by jeffa (Bishop) on Feb 11, 2004 at 21:20 UTC
    More TIMTOWTDI ... reverse makes for cleaner looking code ;)
    $n = reverse substr(reverse($n), 2);
    But that's only good if all your numbers have the same number of right hand side digits ...

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Want to Truncate A Number... NOT round it
by kvale (Monsignor) on Feb 11, 2004 at 20:30 UTC
    I would try this:
    $n = int(1000*$n)/1000;

    -Mark