MantissaAndExponent

New to Analytica 5.2

The MantissaAndExponent function is used to examine the internals of a floating-point number. This is sometimes useful when debugging difficult numeric round-off problems.


MantissaAndExponent( x, integerMantissa)

Returns the mantissa and base-2 exponent of a floating-point number. The function has two return values, so you need to capture them using the syntax

Local (mantissa, exponent) := MantissaAndExponent(x)

The return values are such that «x» is exactly equal to mantissa * 2^exponent. The sign of the mantissa matches the sign of «x».

When the optional «integerMantissa» is omitted or False, then exponent is an integer and for any finite non-zero «x», $ 0.5 \le mantissa \lt 1 $. This variation is equivalent to the frexp(x) function found in many other programming languages.

When «integerMantissa» is True, the mantissa is an integer, $ -2^{53} < mantissa < 2^{53} $, and exponent in an integer or is NaN when «x» is NaN. The exponent returned will usually be smaller by 53 (the number of bits in the mantissa) than the exponent returned when integerMantissa:True is not specified.

Edge cases

The following table describes the various special cases that can arise, and the representation returned in both usage cases.

Real mantissa Integer mantissa
«x» mantissa exponent mantissa exponent
0 (zero) 0 0 0 0
Inf Inf -1 2^52 972
-Inf -Inf -1 -2^52 972
NaN NaN -1 «nan code» NaN
Ordinary (normalized)
number
$ 0.5 \le m \lt 1.0 $ $ -1021 \le e \le 1024 $ $ 2^{52} \le |m| \lt 2^{53} $ $ -971 \le e \le -1074 $
Sub-normalized
number
$ 0.5 \le m \lt 1.0 $ $ -1073 \le e \lt -1021 $ $ -2^{-52} \lt m \lt 2^{52} $ $ -1074 $

Floating point from Mantissa and Exponent

To obtain a floating point number from a mantissa and exponent, the simple expression

mantissa * 2^exponent

returns the corresponding floating point number except in the case where exponent=1024. The problem in the 1024 case is that 2^1024 exceeds the maximum representable finite floating-point number, so 2^exponent overflows to INF, resulting in INF. Because 0.5 <= mantissa < 1, the true number is actually finite. The 1024 case does not occur when using integerMantissa:True, so for that usage the simple expression is sufficient.

To handle the full case, you can introduce the following User-Defined Function:

Function Ldexp(mantissa, exponent)
Definition:
If Not IsNaN(exponent) And exponent=1024
Then (mantissa*2) * 2^1023
Else mantissa * 2^exponent

Next representable float

In some cases it may be convenient to obtain the smallest representable number than is strictly greater than a given value x. This might be denoted as $ x+\epsilon $. This can be obtained using the following User-Defined Function:

Function NextFloat(x)
Definition:
If x=0 Then 2^-1074 Else
Local (mant,e) := MantissaAndExponent(x,true) Do (mant+1)*2^e

Similarly, this UDF gives the largest representable floating point number that is strictly less than x (i.e., $ x - \epsilon $):

Function PrevFloat(x)
Definition:
If x=0 Then -2^-1074 Else
Local (mant,e) := MantissaAndExponent(x,true) Do (mant-1)*2^e

The following edge-cases work as one would expect:

NextFloat(NaN)NaN
PrevFloat(NaN)NaN
NextFloat(Inf)Inf
PrevFloat(Inf) → 1.797693134862316e+308 { i.e., largest finite float }
NextFloat(-Inf) → -1.797693134862316e+308 {i.e., smallest finite float }
PrevFloat(-Inf) → -Inf
NextFloat(0) → 4.9406564584124654e-324 { i.e., smallest positive float }
PrevFloat(0) → -4.9406564584124654e-324 { i.e., largest negative float }
NextFloat(Null)Null
PrevFloat(Null)Null
Comments


You are not allowed to post comments.