The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Data::Float - details of the floating point data type

SYNOPSIS

        use Data::Float qw(have_signed_zero);

        if(have_signed_zero) { ...

        # and many other constants; see text

        use Data::Float qw(
                float_class float_is_normal float_is_subnormal
                float_is_nzfinite float_is_zero float_is_finite
                float_is_infinite float_is_nan
        );

        $class = float_class($value);

        if(float_is_normal($value)) { ...
        if(float_is_subnormal($value)) { ...
        if(float_is_nzfinite($value)) { ...
        if(float_is_zero($value)) { ...
        if(float_is_finite($value)) { ...
        if(float_is_infinite($value)) { ...
        if(float_is_nan($value)) { ...

        use Data::Float qw(float_sign float_parts float_hex);

        $sign = float_sign($value);
        ($sign, $exponent, $significand) = float_parts($value);
        print float_hex($value);

        use Data::Float qw(pow2 mult_pow2);

        $x = pow2($exp);
        $y = mult_pow2($value, $exp);

DESCRIPTION

This module is about the native floating point numerical data type. A floating point number is one of the types of datum that can appear in the numeric part of a Perl scalar.

Floating point values are divided into five subtypes:

normalised

The value is made up of a sign bit (making the value positive or negative), a significand, and exponent. The significand is a number in the range [1, 2), expressed as a binary fraction of a certain fixed length. (Significands requiring a longer binary fraction, or lacking a terminating binary representation, cannot be obtained.) The exponent is an integer in a certain fixed range. The magnitude of the value represented is the product of the significand and two to the power of the exponent.

subnormal

The value is made up of a sign bit, significand, and exponent, as for normalised values. However, the exponent is fixed at the minimum possible for a normalised value, and the significand is in the range (0, 1). The length of the significand is the same as for normalised values. This is essentially a fixed-point format, used to provide gradual underflow. Not all floating point formats support this subtype. Where it is not supported, underflow is sudden, and the difference between two minimum-exponent normalised values cannot be exactly represented.

zero

Depending on the floating point type, there may be either one or two zero values: zeroes may carry a sign bit. Where zeroes are signed, it is primarily in order to indicate the direction from which a value underflowed (was rounded) to zero. Positive and negative zero compare as numerically equal, and they give identical results in most arithmetic operations. They are on opposite sides of some branch cuts in complex arithmetic.

Beware that as of Perl 5.8.7 Perl will lose the sign of a zero if it is used in any arithmetic, including numerical comparisons; only numerically unused zeroes retain their sign. If the string portion of the scalar is generated from the numerical part then it reflects the sign of the zero at the time of the first stringification. Subsequent stringifications return the same string even if the numeric portion has lost its sign in the intervening time.

infinite

Some floating point formats include special infinite values. These are generated by overflow, and by some arithmetic cases that mathematically generate infinities. There are two infinite values: positive infinity and negative infinity.

Perl does not always generate infinite values when normal floating point behaviour calls for it. For example, the division 1.0/0.0 causes an exception rather than returning an infinity.

not-a-number (NaN)

This type of value exists in some floating point formats to indicate error conditions. Mathematically undefined operations may generate NaNs, and NaNs propagate through all arithmetic operations. A NaN has the distinctive property of comparing numerically unequal to all floating point values, including itself.

Perl does not always generate NaNs when normal floating point behaviour calls for it. For example, the division 0.0/0.0 causes an exception rather than returning a NaN.

CONSTANTS

Features

have_signed_zero

Boolean indicating whether floating point zeroes carry a sign. If yes, then there are two zero values: +0.0 and -0.0. If no, then there is only one zero value, considered unsigned.

have_subnormal

Boolean indicating whether there are subnormal floating point values.

have_infinite

Boolean indicating whether there are infinite floating point values.

have_nan

Boolean indicating whether there are NaN floating point values.

It is difficult to reliably generate a NaN in Perl, so in some unlikely circumstances it is possible that there might be NaNs that this module failed to detect. In that case this constant would be false but a NaN might still turn up somewhere. What this constant reliably indicates is the availability of the nan constant below.

Finite Extrema

significand_bits

The number of fractional bits in the significand of finite floating point values.

significand_step

The difference between adjacent representable values in the range [1, 2]. This is equal to 2^-significand_bits.

max_finite_exp

The maximum exponent permitted for finite floating point values.

max_finite_pow2

The maximum representable power of two. This is 2^max_finite_exp.

max_finite

The maximum representable finite value. This is 2^(max_finite_exp+1) - 2^(max_finite_exp-significand_bits).

max_integer

The maximum representable integral value. This is 2^(significand_bits+1) - 1.

min_normal_exp

The minimum exponent permitted for normalised floating point values.

min_normal

The minimum positive value representable as a normalised floating point value. This is 2^min_normal_exp.

min_finite_exp

The base two logarithm of the minimum representable positive finite value. If there are subnormals then this is min_normal_exp - significand_bits. If there are no subnormals then this is min_normal_exp.

min_finite

The minimum representable positive finite value. This is 2^min_finite_exp.

Special Values

pos_zero

The positive zero value. (Exists only if zeroes are signed, as indicated by the have_signed_zero constant.)

neg_zero

The negative zero value. (Exists only if zeroes are signed, as indicated by the have_signed_zero constant.)

pos_infinity

The positive infinite value. (Exists only if there are infinite values, as indicated by the have_infinite constant.)

neg_infinity

The negative infinite value. (Exists only if there are infinite values, as indicated by the have_infinite constant.)

nan

Not-a-number. (Exists only if NaN values were detected, as indicated by the have_nan constant.)

FUNCTIONS

Each "float_" function takes a floating point argument to operate on. The argument must be a native floating point value, or a native integer (which will be silently converted to floating point). Giving a non-numeric argument will cause mayhem. See "is_number" in Params::Classify for a way to check for numericness.

Classification

Each "float_is_" function returns a simple boolean result.

float_class(VALUE)

Determines which of the five classes described above VALUE falls into. Returns "NORMAL", "SUBNORMAL", "ZERO", "INFINITE", or "NAN" accordingly.

float_is_normal(VALUE)

Returns true iff VALUE is a normalised floating point value.

float_is_subnormal(VALUE)

Returns true iff VALUE is a subnormal floating point value.

float_is_nzfinite(VALUE)

Returns true iff VALUE is a non-zero finite value (either normal or subnormal; not zero, infinite, or NaN).

float_is_zero(VALUE)

Returns true iff VALUE is a zero. If zeroes are signed then both signs qualify.

float_is_finite(VALUE)

Returns true iff VALUE is a finite value (either normal, subnormal, or zero; not infinite or NaN).

float_is_infinite(VALUE)

Returns true iff VALUE is an infinity (either positive infinity or negative infinity).

float_is_nan(VALUE)

Returns true iff VALUE is a NaN.

Examination

float_sign(VALUE)

Returns "+" or "-" to indicate the sign of VALUE. If zero is unsigned then it is treated as positive. dies if VALUE is a NaN.

Currently this is not reliable when applied to zeroes. In that case it operates by stringification, and so may be confused by dualvars and by zeroes that have lost their signs following earlier stringification. This behaviour may change in the future, especially if Perl gets better handling of signed zeroes.

float_parts(VALUE)

Divides up a non-zero finite floating point value into sign, exponent, and significand, returning these as a three-element list in that order. The significand is returned as a floating point value, in the range [1, 2) for normalised values, and in the range (0, 1) for subnormals. dies if VALUE is not finite and non-zero.

float_hex(VALUE)

Encodes the exact value of VALUE as a hexadecimal fraction, returning the fraction as a string. Specifically, for finite values the output is of the form "s0xm.fffffpeee", where "s" is the sign, "m" is the integral part of the significand ("1" for normals and "0" for subnormals), "fffff" is the fractional part of the significand in hexadecimal, and "eee" is the exponent in decimal with a sign. The number of significand fraction digits is constant, being just sufficient to represent all the bits of the significand.

Zeros are encoded as "+0.0" and "-0.0", with the same unreliability noted above for float_sign. If zero is unsigned then it is encoded as "+0.0". Infinities are encoded as "+inf" and "-inf". NaNs are encoded as "nan".

Manipulation

pow2(EXP)

EXP must be an integer. Returns the value two the the power EXP. dies if that value cannot be represented exactly as a floating point value. The return value may be either normalised or subnormal.

mult_pow2(VALUE, EXP)

EXP must be an integer, and VALUE a floating point value. Multiplies VALUE by two to the power EXP. This gives exact results, except in cases of underflow and overflow. The range of EXP is not constrained. All normal floating point multiplication behaviour applies.

BUGS

Perl (as of version 5.8.7) doesn't reliably maintain the sign of a zero. All handling of the sign of zeroes in this module is a bit screwy as a result. Avoid relying on correct signed-zero handling, even if you know your hardware handles it correctly.

NaN handling is generally not well defined in Perl. Arithmetic with a mathematically undefined result may either die or generate a NaN. Avoid relying on any particular behaviour for such operations, even if your hardware's behaviour is known.

AUTHOR

Andrew Main (Zefram) <zefram@fysh.org>

COPYRIGHT

Copyright (C) 2006 Andrew Main (Zefram) <zefram@fysh.org>

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.