Perl does not distinguish between integer and floating-point numbers when doing arithmetic. Machine Arithmetic where the operands and the result are all integral is accurate as long as all values can be properly represented by the platform. Unfortunately, floating-point arithmetic is inherently imprecise, and can trip programmers who are not aware of its usage.

Noncompliant Code Example

This noncompliant code example appears to print ten very large numbers, and on 64-bit machines, it indeed does so.

However, when run on a 32-bit machine, the loop will never terminate. This is because the numbers, while integral, are too large to be represented internally as integers, so they are represented as 32-bit floating-point numbers. Even with 24-bit mantissas, the numbers are too large for an increment of 1 to be noticed. Consequently, the program forever prints out the number 1e+16.

my $x = 10000000000000000;  # 1e+16
for (my $y = $x; $y <= $x + 5; $y += 1) {
  print "$y\n";
}

Compliant Solution

This compliant solution ensures that the loop counter computation involves numbers less than 248 (that is, 281,474,976,710,656).

my $x = 10000000000000000;  # 1e+16
for (my $y = 0; $y <= 5; $y += 1) {
  my $z = $x + $y;
  print "$z\n";
}

On a 32-bit machine, this program terminates normally after printing the following:

1e+16
1e+16
1e+16
1e+16
1e+16
1e+16

Compliant Solution

This compliant solution uses the Bignum module to ensure precise computation. The Bignum module is available in CPAN, but became part of Perl's standard library for version 5.8.

use bignum;
my $x = 10000000000000000;  # 1e+16
for (my $y = $x; $y <= $x + 5; $y += 1) {
  print "$y\n";
}

On a 32-bit machine, this program terminates normally after printing the following:

10000000000000000
10000000000000001
10000000000000002
10000000000000003
10000000000000004
10000000000000005

Risk Assessment

Failing to understand the limitations of floating-point numbers can result in unexpected computational results and exceptional conditions, possibly resulting in a violation of data integrity.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

INT01-PL

medium

probable

high

P4

L3

Bibliography

[Gough 2005] Section 8.6, "Floating-point issues"
[IEEE 754 2006] 
[CPAN]Florian Ragwitz, bignum
[Meta CPAN]perlnumber