dnvrdave
dnvrdave

Reputation: 117

Using Perl to split a float

Why did I lose precision using split? My goal is to get just the fractional part, all of it.

$a = 123456789.123456789;
@b = split(/\./, $a);
$baseDec = "." . $b[1];

Above gives $baseDec == .123457

But this gives the correct precision: Is it the right way to do it? CORRECTION: THIS GIVES THIS SAME BAD PRECISION! I did not properly test the code. Sorry!

$a = 123456789.123456789;
@b = split(/\./, $a);
$baseInt = $b[0];
$baseDec = $a - $baseInt;

Should I be using Math::BigFloat?

Edit: $a should be a string $a = "123456789.123456789"; and then the original code works. Until I figure out how to get my Perl to work with longdouble, I can't test the original question. The answer seems to be that I lost precision because $a is being stored in a double (52 bits ~ 15 decimal digits, as @Ben stated below). print $a gives 123456789.123457.

Upvotes: 5

Views: 2936

Answers (4)

Ben Grimm
Ben Grimm

Reputation: 4371

You lost precision because 123456789.123456789 is a numeric literal which, by default, the Perl compiler stores in a double (52 bits, ~15 decimal digits) $a. Next, when @b = split(/\./, $a); runs, $a is implicitly coerced into a string before it can be split.

If your Perl were compiled to use longdoubles (See: perl -V:uselongdouble and perl -V:doublesize), the numeric literal would have been represented with 80 bits (~21 decimal digits) and string coercion.

Upvotes: 4

GWP
GWP

Reputation: 131

IF you're going to treat it as a string, do so all the way through. You wouldn't assign a string without quoting, right?

my $a = "123456789.123456789";

Upvotes: 3

René Nyffenegger
René Nyffenegger

Reputation: 40489

You can use int:

 $a = 123456789.123456789;
 $baseDec = $a - int($a);

Upvotes: 5

AlfredoVR
AlfredoVR

Reputation: 4287

You can get it by using sprintf:

my $a = 123456789.123456789;
my @b = split(/\./, sprintf("%.8f",$a));
my $baseDec = "." . $b[1];
print $baseDec;

Upvotes: 1

Related Questions