-3

I'm getting confused with floating point number in c programming

#include <stdio.h>

int main()
{
    float a = 255.167715;
    printf("%f", a);
    return 0;
} // it print value of 255.167709

Why it produce value like so? To be honest can you tell how it actually works in C programming?

alk
  • 69,737
  • 10
  • 105
  • 255
Md. A. Barik
  • 429
  • 5
  • 12
  • Welcome to the C programming language where things are frequently confusing. – machine_1 Jul 21 '19 at 15:04
  • Related: https://stackoverflow.com/q/9765744/694576 – alk Jul 21 '19 at 15:06
  • floats and doubles have finite precsion, and use values that are close enough if you assign values that cannot be stored exactly. This problem applies to all computer and even paper calculations (paper is finite), but the real life impact can be lessened by chosing appropriate datatypes, respectively larger paper – Peter Jul 21 '19 at 15:07
  • You got 24 bits for storing digits in a float, which is log10(2^24) = 7.2247 digits. But your number needs log10(255167715) = 8.4068257246 digits. Therefore the last 1.1821 digits can't be stored anymore. – Johannes Schaub - litb Jul 21 '19 at 15:09
  • Also see [this](https://www.youtube.com/watch?v=PZRI1IfStY0) – Aykhan Hagverdili Jul 21 '19 at 15:09
  • https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Dave Newton Jul 21 '19 at 15:36

2 Answers2

2

In binary, 255.167715 is approximately 11111111.001010101110111101011110110010000000110001110…2. In your C implementation, most likely, the source code 255.167715 is converted to 11111111.0010101011101111010111101100100000001100011102, which is 255.16771499999998695784597657620906829833984375, because 255.167715 is a double constant, and that is the closest value representable in your implementation’s double type to the decimal number 255.167715, because the double type has only 53-bit significands. (A significand is the fraction portion of a floating-point number. There is also a sign and an exponent portion.)

Then, for float a = 255.167715;, this double value is converted to float. Since the float type has only 24-bit significands, the result is 11111111.00101010111011112, which is 255.1677093505859375 in decimal.

When you print this with the default formatting of %f, six digits after the decimal place are used, so it prints “255.167709”.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Exactly what I want! Thanks dude – Md. A. Barik Jul 22 '19 at 00:37
  • float b = 19491.1234355 printf("%f", b) // output 19491.123047` but you said it should be 19491.123046875 so 19491.123046! What's wrong in my code? – Md. A. Barik Jul 22 '19 at 01:28
  • @Md.A.Barik: The `%f` format specification uses six digits after the decimal place. To print more, you can use `%.99f` or `%.99g`. – Eric Postpischil Jul 22 '19 at 02:18
  • @Epic Postpischil output: 19491.123046 in calculation but it shows: 19491.123047 when I run the program. Can you tell me how it works? – Md. A. Barik Jul 22 '19 at 04:12
  • @Md.A.Barik: The value is rounded when formatting. Since 19491.123047 is closer to 19491.123046875 than 19491.123046 is, it is used. (Note: The C standard requires correct rounding only up to `DECIMAL_DIG` digits. After that, it allows some flexibility.) – Eric Postpischil Jul 22 '19 at 10:27
0

The short answer is that there is no such single-precision floating-point number as 255.167715. This is true for any computer using IEEE 754 floating-point formats; the situation is not unique to C. As a single-precision floating-point number, the closest value is 255.167709.

Single-precision floating point gives you the equivalent of 7 or so decimal digits of precision. And as you can see, the input you gave and the output you got agreed to seven places, namely 255.1677. Any digits past that are essentially meaningless.

For much more about the sometimes-surprising aspects of floating-point math, see "Is floating point math broken?".

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • The assertion 255.167715 is not representable in any IEEE-754 floating-point format is incorrect. As the page you link to states, IEEE-754 includes decimal floating-point formats. Additionally, 255.167709 is not the closest number to 255.167715 that is representable in an IEEE-754 binary format, because it is not representable in a binary format. – Eric Postpischil Jul 21 '19 at 16:48