Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The minimum positive float value by direct calculation is different from the FLT_MIN in <float.h>

I want to directly calculate the minimum value of the float type, and here is my algorithm(Suppose that the encoding of floating-point number confirms to the IEEE 754 standard):

#include <math.h>
#include <limits.h>
#include <float.h>
#include <stdio.h>

float float_min()
{
    int exp_bit = CHAR_BIT * sizeof(float) - FLT_MANT_DIG;
    float exp = 2 - pow(2, exp_bit - 1);

    float m = pow(2, -(FLT_MANT_DIG - 1));

    return m * pow(2, exp);
}

int main()
{
    printf("%g\n", float_min());
}

The output is 1.4013e-45. However, I find the the value of FLT_MIN in the C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\float.h is 1.175494351e-38F. Who is wrong?

like image 857
Shangchih Huang Avatar asked Aug 15 '17 12:08

Shangchih Huang


People also ask

What is float H used for?

The header float. h contains macros that expand to various limits and parameters of the standard floating-point types. The macros, as defined on ISO 9899:1999 section 5.2. 4.2.

What is the largest floating point number in C?

short: min: -32768 max: 32767 int: min: -2147483648 max: 2147483647 long: min: -2147483648 max: 2147483647 float: min: 1.17549e-038 max: 3.40282e+038 double: min: 2.22507e-308 max: 1.79769e+308 long double: min: 2.22507e-308 max: 1.79769e+308 unsigned short: min: 0 max: 65535 unsigned int: min: 0 max: 4294967295 ...

What is the minimum negative value a float can represent?

The minimum negative value that float can represent is sys.float_info.max with -. Values smaller than this are treated as negative infinity. You can get the minimum positive normalized value with sys.float_info.min.

How to find the minimum value between two float values?

The min () method of Java Float class returns the float having minimum value between two float values. The result returned is same as by invoking Math.min () method. Here a & b are the two float operands that are compared.

What is the minimum positive normalized value of float in Python?

sys.float_info.min is the minimum positive normalized value. Values that their exponent part is 0 and their mantissa part is not 0 are called denormalized numbers. The minimum positive denormalized value can be converted from a hexadecimal string as follows.

How to use Min () method of Java Float class?

The min () method of Java Float class returns the float having minimum value between two float values. The result returned is same as by invoking Math.min () method. Here a & b are the two float operands that are compared. The min () method returns the lesser value between a and b. Scanner scanner = new Scanner (System.in);


2 Answers

Although this question has been asked and answered several times before, I don't see any answer that is actually correct. The key is that FLT_MIN is the smallest normalized value that can be represented. Back in the olden days that was all that mattered. Then Intel came along and introduced subnormal values, which reduce precision in order to represent values closer to 0. Subnormals are values with the minimum exponent and a fraction whose high bits are all zeros. It follows from that that the smallest non-zero subnormal value has a fraction that's all zeros except for the lowest bit, which is a 1. That's the smallest value that can be represented, but when you're down there, changing a bit here and there makes a large change in the value, so these things have to be used with great care.

EDIT, to clarify "normalization":

Suppose we're writing decimal values: 6.02x10^23, .602*10^24, 60.2*10^22. Those all represent the same value, but they clearly look different. So let's introduce a rule for writing decimal values: every value must have exactly one non-zero digit to the left of the decimal point. So the "normalized" form of that value is 6.02x10^23, and if we have a value written in a non-normalized form we can move the decimal point and adjust the exponent to preserve the value and put it into normalized form.

IEEE floating-point does the same thing: the rule is that the high bit of the fraction must always be 1, and any calculation has to adjust the fraction and the exponent of its result to satisfy that rule.

When we write decimal values that are really close to 0 that's not a problem: we can make the exponent as small as we need to, so we can write numbers like 6.02*10^-16384. With floating-point values we can't do that: there a minimum exponent that we can't go below. In order to allow smaller values, the IEEE requirements say that when the exponent is the smallest representable value, the fraction doesn't have to be normalized, that is, it doesn't have to have a 1 in its high bit. In writing decimal values, that's like saying we can have a 0 to the left of the decimal point. So if our decimal rule said that the lowest allowable exponent is -100, the smallest normalized value would be 1.00x10^-100, but smaller value could be represented as non-normalized: 0.10*10^-100, 0.01*10^-100, etc.

Now add a requirement to our decimal rules that we can only have three digits: one to the left of the decimal point and two to the right. That's like the floating-point fraction in that it has a fixed number of digits. So for small normal values we have three digits to play with: 1.23*10^-100. For smaller values we use leading zeros, and the remaining digits have less precision: 0.12*10^-100 has two digits, and 0.01*10^-100 has only 1. That's also how floating-point subnormals work: you get fewer and fewer significant bits as you get farther and farther below the minimum normalized value, until you run out of bits and you get 0.

EDIT: to clarify terminology, the IEEE-754 standard referred to those values that are greater than 0 and less then the minimum normalized value as denormals; the latest revision of IEEE-754 refers to them as subnormals. They mean the same thing.

like image 57
Pete Becker Avatar answered Sep 19 '22 01:09

Pete Becker


Your result 1.4013e-45 is denormal minimal positive float value, also known as FLT_TRUE_MIN which is equal to 1.401298464e-45F.

FLT_MIN is normalized minimal positive float value (1.175494351e-38F)

like image 28
ikleschenkov Avatar answered Sep 19 '22 01:09

ikleschenkov