Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Java

...

uses

...

the

...

IEEE

...

754

...

standard

...

for

...

floating

...

-point

...

representation.

...

In

...

this

...

representation,

...

floats

...

are

...

encoded

...

using

...

1

...

sign

...

bit,

...

8

...

exponent

...

bits,

...

and

...

23

...

mantissa

...

bits.

...

Doubles

...

are

...

encoded

...

and

...

used

...

exactly

...

the

...

same

...

way,

...

except

...

they

...

use

...

1

...

sign

...

bit,

...

11

...

exponent

...

bits,

...

and

...

52

...

mantissa

...

bits.

...

These

...

bits

...

encode

...

the

...

values

...

of

...

s,

...

the

...

sign;

...

M,

...

the

...

significand;

...

and

...

E,

...

the

...

exponent.

...

Floating

...

-point

...

numbers

...

are

...

then

...

calculated

...

as

...

(-1)

...

s *

...

M

...

*

...

2 E.

Image Added

Ordinarily, all of the mantissa bits are used to express significant figures, in addition to a leading 1, which is implied and consequently omitted. As a result, floats have 24 significant bits of precision, and doubles have 53 significant bits of precision. Such numbers are called normalized numbers.

When the value to be represented is too small to encode normally, it is encoded in denormalized form, indicated by an exponent value of Float.MIN_EXPONENT - 1 or Double.MIN_EXPONENT - 1. Denormalized floating-point numbers have an assumed 0 in the ones' place and have one or more leading zeros in the represented portion of their mantissa. These leading zero bits no longer function as significant bits of precision; consequently, the total precision of denormalized floating-point numbers is less than that of normalized floating-point numbers. Note that even using normalized numbers where precision is required can pose a risk. See rule NUM04-J. Do not use floating-point numbers if precise computation is required for more information.

Using denormalized numbers can severely impair the precision of floating-point calculations; as a result, denormalized numbers must not be used.

Detecting Denormalized Numbers

The following code tests whether a float value is denormalized in FP-strict mode or for platforms that lack extended range support. Testing for denormalized numbers in the presence of extended range support is platform-dependent; see rule NUM53-J. Use the strictfp modifier for floating-point calculation consistency across platforms for additional information.

Code Block
 ^E^.

Ordinarily all of the mantissa bits are used to express significant figures, in addition to a leading 1, which is implied and, therefore, left out. Floats consequently have 24 significant bits of precision; doubles have 53 significant bits of precision. Such numbers are called normalized numbers. All floating point numbers are limited in this sense that they have fixed precision.

When the value to be represented is too small to encode normally, it is encoded in _denormalized_ form, indicated by an exponent value of {{Float.MIN_EXPONENT - 1}} or {{Double.MIN_EXPONENT - 1}}. Denormalized floating point numbers have an assumed 0 in the ones place, and have zero or more leading zeros in represented portion of their mantissa. These leading zero bits no longer function as significant bits of precision; consequently, the total precision of denormalized floating point numbers is less than that of normalized floating point numbers. Note that even use of normalized numbers where precision is required can pose a risk. See recommendation [NUM07-J. Avoid using floating point numbers when precise computation is required]. for more information. 

Use of denormalized numbers can severely impair the precision of floating point calculations; consequently denormalized numbers must not be used.

h3. Detecting Denormalized Numbers

The following code tests whether a {{float}} value is denormalized in strictfp mode, or for platforms that lack extended range support. Testing for denormalized numbers in the presence of extended range support is platform dependent; see [NUM09-J. Use the strictfp modifier for floating point calculation consistency across platforms] for additional information.

{{code}}
strictfp public static boolean isDenormalized(float val) {
  if (val == 0) {
    return false;
  }
  if ((val > -Float.MIN_NORMAL) && (val < Float.MIN_NORMAL)) {
    return true;
  }
  return false;
}
{{code}}
Testing whether values of type {{double}} are denormalized is exactly analogous. 

h3. Print Representation of Denormalized Numbers

Denormalized numbers can also be troublesome because their printed representation is unusual. Floats and normalized doubles, when formatted with the {{%a}} specifier begin with a leading nonzero digit. Denormalized doubles can begin with a leading zero to the left of the decimal point in the mantissa.

The following program produces the following output:

{code}

Testing whether values of type double are denormalized is analogous.

Print Representation of Denormalized Numbers

Denormalized numbers can also be troublesome because their printed representation is unusual. Floats and normalized doubles, when formatted with the %a specifier, begin with a leading nonzero digit. Denormalized doubles can begin with a leading zero to the left of the decimal point in the mantissa.

Here is a small program, along with its output, that demonstrates the print representation of denormalized numbers.

Code Block
strictfp class FloatingPointFormats {
    public static void main(String[] args) {
        float x = 0x1p-125f;
        double y = 0x1p-1020;
        System.out.format("normalized float with %%e    : %e\n", x);
        System.out.format("normalized float with %%a    : %a\n", x);
        x = 0x1p-140f;
        System.out.format("denormalized float with %%e  : %e\n", x);
        System.out.format("denormalized float with %%a  : %a\n", x);
        System.out.format("normalized double with %%e   : %e\n", y);
        System.out.format("normalized double with %%a   : %a\n", y);
        y = 0x1p-1050;
        System.out.format("denormalized double with %%e : %e\n", y);
        System.out.format("denormalized double with %%a : %a\n", y);
    }
}
{code}

{code}
Code Block
normalized float with %e    : 2.350989e-38
normalized float with %a    : 0x1.0p-125
denormalized float with %e  : 7.174648e-43
denormalized float with %a  : 0x1.0p-140
normalized double with %e   : 8.900295e-308
normalized double with %a   : 0x1.0p-1020
denormalized double with %e : 8.289046e-317
denormalized double with %a : 0x0.0000001p-1022
{code}


h2. Noncompliant Code Example

This code attempts to reduce a floating point number to a denormalized value and then restore the value.

{code:bgColor=#FFCCCC}#include <stdio.h>

Noncompliant Code Example

This noncompliant code example attempts to reduce a floating-point number to a denormalized value and then restore the value.

Code Block
bgColor#FFCCCC
float x = 1/3.0f;
System.out.println("Original      : " + x);
x = x * 7e-45f;
System.out.println("Denormalized? : " + x);
x = x / 7e-45f;
System.out.println("Restored      : " + x);
{code}

This operation is

Because this operation is imprecise, this code produces the following output when run in FP-strict mode:

Code Block
Original imprecise. The code produces the following output:

{code}
Original      : 0.33333334
Denormalized? : 2.8E-45
Restored      : 0.4
{code}

h2. Compliant Solution

Do not use code that could use denormalized numbers. When calculations using {{float}} produce denormalized numbers, use of {{double}} may provide sufficient precision.

{code:bgColor=#ccccff}#include <stdio.h>

Compliant Solution

Do not use code that could use denormalized numbers. When calculations using float produce denormalized numbers, use of double can provide sufficient precision.

Code Block
bgColor#ccccff
double x = 1/3.0;
System.out.println("Original      : " + x);
x = x * 7e-45;
System.out.println("Denormalized? Normalized: " + x);
x = x / 7e-45;
System.out.println("Restored      : " + x);
{code}

This

...

code

...

produces

...

the

...

following

...

output in FP-strict mode:

Code Block
Original:

{code}
Original      : 0.3333333333333333
Denormalized? Normalized: 2.333333333333333E-45
Restored      : 0.3333333333333333
{code}

h2. Exceptions

*NUM08-EX1:* Denormalized numbers are acceptable when competent numerical analysis demonstrates that the computed values will meet all accuracy and behavioral requirements that are appropriate to the application. Note that "competent numerical analysis" generally requires a specialized professional numerical analyst; lesser levels of rigor fail to qualify for this exception.
  
h2. Risk Assessment

Floating point numbers are an approximation; denormalized floating point numbers are a less precise approximation. Use of denormalized numbers can cause unexpected loss of precision, and consequently can lead to incorrect or unexpected results. Although the severity stated below for violations of this guideline is "low", applications that require accurate results should consider the severity of violations to be high.

|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| NUM08-J  | low | probable | high | {color:green}{*}P2{*}{color} | {color:green}{*}L3{*}{color} |

h2. Related Guidelines

CERT C Secure Coding Standard [seccode:FLP05-C. Don't use denormalized numbers]


h2. Bibliography

\[[IEEE 754|AA. Bibliography#IEEE 754 2006]\]
\[[Bryant 2003|AA. Bibliography#Bryant 03]\] Computer Systems: A Programmer's Perspective. Section 2.4 Floating Point

----
[!The CERT Oracle Secure Coding Standard for Java^button_arrow_left.png!|NUM06-J. Provide mechanisms to handle unsigned data when required]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_up.png!|03. Numeric Types and Operations (NUM)]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_right.png!|NUM08-J. Do not use denormalized numbers]

Exceptions

NUM05-J-EX0: Denormalized numbers are acceptable when suitable numerical analysis demonstrates that the computed values meet all accuracy and behavioral requirements appropriate to the application.

Risk Assessment

Floating-point numbers are an approximation; denormalized floating-point numbers are a less precise approximation. Use of denormalized numbers can cause unexpected loss of precision, possibly leading to incorrect or unexpected results. Although the severity for violations of this rule is low, applications that require accurate results should make every attempt to comply.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

NUM05-J

low

probable

high

P2

L3

Related Vulnerabilities

CVE-2010-4476 [CVE 2008 ] reports a vulnerability in the Double.parseDouble() method in Java 1.6 update 23 and earlier, Java 1.5 update 27 and earlier, and 1.4.2_29 and earlier. This vulnerability causes a denial of service when this method is passed a crafted string argument. The value 2.2250738585072012e-308 is close to the minimum normalized, positive, double-precision floating-point number; when encoded as a string it triggers an infinite loop of estimations during conversion to a normalized or denormalized double.

Related Guidelines

Bibliography

[Bryant 2003]

Computer Systems: A Programmer's Perspective, Section 2.4, Floating Point

[CVE 2008 ]

CVE-2010-4476

[IEEE 754]

 

[Seacord 2015] Image result for video iconImage Added NUM05-J. Do not use denormalized numbers LiveLesson

 

...

Image Added Image Added Image Added