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

Dear Monks, I need to store two portions of a number in two different scalars. For sake of argument we will call the number 2.33 and we will store it in $x. We'll call the two scalars $y and $z. I can easily obtain the first number I need with $y = int($x) but what is the most effective way of storing the decimal portion in $z ? Thanks, /bwb.

Replies are listed 'Best First'.
Re: splitting a decimal number..
by mpeters (Chaplain) on Jan 05, 2005 at 22:47 UTC
      Hah. Ok. It's been a long day and we'll just pretend I didn't need to be reminded how to subtract.

      /bwb.
Re: splitting a decimal number..
by punkish (Priest) on Jan 05, 2005 at 22:48 UTC
    my $x = 2.33; my $y = int($x); my $z = $x - $y;
Re: splitting a decimal number..
by dave_the_m (Monsignor) on Jan 05, 2005 at 22:49 UTC
    er...
    $y = int $x; $z = $x - $y;
    Of course you may run into problems with negative numbers.

    Dave.

      Thanks all.
Re: splitting a decimal number..
by Juerd (Abbot) on Jan 05, 2005 at 22:55 UTC

    This solution is far from perfect, but it *works* (as long as the number stringifies normally)

    my ($y, $z) = split /\./, $x;
    Sometimes you can get away with doing stringy things on numbers. It can be a time saver if you're in a hurry and out of inspiration.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      That's close to how I was trying to do it, but occasionally was yielding some strange results depending on the data I fed to it. Anyway, I've got it worked out now.

      /bwb.
Re: splitting a decimal number..
by aquarium (Curate) on Jan 06, 2005 at 01:23 UTC
    Depends if you want $z to be 0.23 or just 23, and also depends if you want proper numbers that can be mathematically combined to re-produce original, e.g. $x = -2.23, $y = -2.0, $z = -0.23. If this is the case, or if it's even more complicated, by having to carry proper precision e.g. -2.00, then regexes would work best. if you only care about positive results like $y = 2 and $z = 0.23, then int and subtraction is enough.
    if you're more adventurous:
    $precision = 100; # 2 decimal point assumed precision $x = -2.33; $y = int($x); $z = ((abs($x) * $precision) % (abs($y)*$precision)) / $precision;
    the hardest line to type correctly is: stty erase ^H
Re: splitting a decimal number..
by sgifford (Prior) on Jan 06, 2005 at 01:42 UTC
    You can use POSIX::modf:
    $ perl -MPOSIX -le ' my($f,$i)=POSIX::modf(3.14); print "f=$f; i=$i";' f=0.14; i=3

    That might be more reliable than simple subtraction with negative numbers.

Re: splitting a decimal number..
by gube (Parson) on Jan 06, 2005 at 03:37 UTC
    Hi, Just try this using split function
    $x = "2.33"; ($y,$z) = split(/\./, $x); print "$y"; print "\n$z"; o/p: 2 33
    Regards, Gubendran.L
Re: splitting a decimal number..
by jbrugger (Parson) on Jan 06, 2005 at 06:16 UTC
    Hi,
    It all depend on what you exactky want. e.g:
    #!/usr/bin/perl -t -w use strict; sub dosplitMe () { my ($x,$justSplitMe) = @_; if ($justSplitMe) { my ($y, $z) = split(/\./, $x); return ($y, $z); } else { # there might be stuff before first integer... my ($y,$z); if ($x =~ m/(\D+)?(\d+)\.(\d+)/) { ($y, $z) = ($1.$2 , $1.$3); } return ($y, $z); } } my $num1 = 123.456; my $num2 = -123.456; my $num3 = "abc123.123"; my @a; @a = &dosplitMe($num1,1); print ("1: $a[0] - $a[1] \n"); @a = &dosplitMe($num2,1); print ("2: $a[0] - $a[1] \n"); @a = &dosplitMe($num2,0); print ("3: $a[0] - $a[1] \n"); @a = &dosplitMe($num3,1); print ("4: $a[0] - $a[1] \n"); @a = &dosplitMe($num3,0); print ("5: $a[0] - $a[1] \n");

    *** update: *** Or even better:
    #!/usr/bin/perl -t -w use strict; sub dosplitMe () { my ($x,$separator,$justSplitMe) = @_; if ($justSplitMe) { if ($x =~ m /(.*)?$separator(.*)/) { return ($1,$2); } } else { # there might be stuff before first integer... if ($x =~ m/(\D+)?(\d+)$separator(\d+)/) { return ($1.$2 , $1.$3); } } } my $num1 = 123.456; my $num2 = -123.456; my $num3 = "abc123,123"; my @a; @a = &dosplitMe($num1,'\.',1); print ("1: $a[0] - $a[1] \n"); @a = &dosplitMe($num2,'\.',1); print ("2: $a[0] - $a[1] \n"); @a = &dosplitMe($num2,'\.',0); print ("3: $a[0] - $a[1] \n"); @a = &dosplitMe($num3,',', 1); print ("4: $a[0] - $a[1] \n"); @a = &dosplitMe($num3,',', 0); print ("5: $a[0] - $a[1] \n");