diff --git a/lib/PPI/Token/Number/Exp.pm b/lib/PPI/Token/Number/Exp.pm index 74161ef0..241ce16c 100644 --- a/lib/PPI/Token/Number/Exp.pm +++ b/lib/PPI/Token/Number/Exp.pm @@ -52,8 +52,28 @@ sub literal { my $neg = $mantissa =~ s/^\-//; $mantissa =~ s/^\./0./; $exponent =~ s/^\+//; - my $val = $mantissa * 10 ** $exponent; - return $neg ? -$val : $val; + + # This algorithm is reasonably close to the S_mulexp10() + # algorithm from the Perl source code, so it should arrive + # at the same answer as Perl most of the time. + my $negpow = 0; + if ($exponent < 0) { + $negpow = 1; + $exponent *= -1; + } + + my $result = 1; + my $power = 10; + for (my $bit = 1; $exponent; $bit = $bit << 1) { + if ($exponent & $bit) { + $exponent = $exponent ^ $bit; + $result *= $power; + } + $power *= $power; + } + + my $val = $neg ? 0 - $mantissa : $mantissa; + return $negpow ? $val / $result : $val * $result; } diff --git a/t/07_token.t b/t/07_token.t index 155fbddc..76f6f971 100644 --- a/t/07_token.t +++ b/t/07_token.t @@ -55,7 +55,7 @@ SCOPE: { '0.0e-10' => '10e', '0.0e+10' => '10e', '0.0e100' => '10e', - '1_0e1_0' => '10e', # Known to fail on 5.6.2 + '1_0e1_0' => '10e', '0b' => 2, '0b0' => 2, '0b10' => 2,