7

A question about floating-point precision in Go made me wonder how C handles the problem.

With the following code in C:

float a = 0.1;

Will a have the closest IEEE 754 binary representation of:

00111101110011001100110011001101 (Decimal:  0.10000000149011612)

or will it just crop it to:

00111101110011001100110011001100 (Decimal:  0.09999999403953552)

Or will it differ depending on compiler/platform?

Community
  • 1
  • 1
ANisus
  • 74,460
  • 29
  • 162
  • 158

2 Answers2

6

An implementation is allowed to do either (or even be off by one more):

For decimal floating constants, and also for hexadecimal floating constants when FLT_RADIX is not a power of 2, the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner.

(C11, §6.4.4.2/3)

Since C99, we've had hexadecimal floating point constants so that you can specify precisely the bits you want (assuming that the implementation offers binary floating point :) ), so you could have said, for example:

float a = 0x1.99999Ap-4;

For IEEE 754 32-bit floats:

#include <stdio.h>
int main() {
  float a = 0.1;
  float low  = 0x0.1999999p0;
  float best = 0x0.199999ap0;
  float high = 0x0.199999bp0;
  printf("a is %.6a or %.16f, which is either %.16f, %.16f or %.16f\n",
          a, a, low, best, high);
  return 0;
}
rici
  • 234,347
  • 28
  • 237
  • 341
  • I didn't know C11 standard was that expensive to get a copy of. Nor did I know about hexadecimal floating points. Thanks! Hmm.. but I wonder why someone would downvote the answer. – ANisus Mar 12 '14 at 01:04
  • @ANisus: You can download for free something very similar to the C11 standard. See http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents – rici Mar 12 '14 at 01:06
  • It's theoretically compiler dependent, but practically, it will be rounded to nearest: most implementations adhere to other standards like IEEE-754 or ISO 10967 (at least partially) – aka.nice Mar 12 '14 at 03:15
  • @aka.nice: Rounding correctly is difficult. Not all implementations bother to be precise (but they should manage to meet the slightly relaxed standard). See, for example, http://www.exploringbinary.com/incorrectly-rounded-conversions-in-visual-c-plus-plus/ – rici Mar 12 '14 at 03:47
  • @rici I know how difficult it is, especially to do it efficiently, but plenty other things are difficult w.r.t. to IEEE 754 (I.e. try to implement some math function with monotonicity, or max error constraints), so except for some cases of exotic HW, relying on state of the art libc is a good and easy start. – aka.nice Mar 12 '14 at 10:55
  • @aka.nice That is the first time I have heard Windows described as exotic, but whatever. Did you read that link? Or maybe I just don't understand what your point is. – rici Mar 12 '14 at 14:44
  • @rici you are right, exotic does not qualify here, but maybe neither state of the art in this case? I live with a mixture of mingw and/or ICC setups, so maybe I'm the exotic one ;) – aka.nice Mar 12 '14 at 16:16
0

Unspecified by the standard, but testing on some local hardware:

#include <stdio.h>

int
main( int argc, char **argv )
{
float   a = 0.1;
double  b = a;

printf("%.16f\n", b );
}

0.1000000014901161

user3303729
  • 284
  • 1
  • 6