1

I have two unsigned long long numbers l1 and l2. I cast those numbers to float and save them as f1 and f2.

f1 = (float) l1;
f2 = (float) l2;

Now consider l1 > l2 by some arbitrary amount, say 100.

Can there be a case such that f1 < f2 ?. (Here f1 is converted from l1 which is greater than l2). If yes, can you please demonstrate how to find such a number?

sizeof(float) = 4 and sizeof(unsigned long long) = 8.
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
jvc
  • 604
  • 2
  • 12
  • 33
  • Yeah. If `float` is represented as an IEEE-754 single-precision number, then it only has at most 7 decimal digits of precision. So you can easily generate two huge `unsigned long long`s that differ by 100, yet they equal when converted to `float`s. –  Dec 17 '13 at 12:56
  • 2
    @H2CO3 The question is whether f1 < f2 is possible. I do not think it is (f1 == f2 is clearly possible). – Pascal Cuoq Dec 17 '13 at 12:59
  • @PascalCuoq Oops, sorry, missed that. [Here's a demo for the false equality](http://ideone.com/rE3ltT), though. –  Dec 17 '13 at 13:01
  • There are many wonky, unreliable and plain buggy floating-point implementations out there, both in hardware and software. Plus the C language guarantees virtually nothing beyond the some minimum limits on precision and range. I'm sure you could dig out some ancient minicomputer somewhere where this might fail if you looked hard enough but in practice on decent modern IEEE-754 systems it will be fine. – doynax Dec 17 '13 at 13:29

1 Answers1

6

Can there be a case such that f1 < f2

No: For any rounding mode, the conversion from integer to float is increasing. As long as you do not change the rounding mode between the conversion of l1 and that of l2, f1 and f2 are in the same order as l1 and l2 (they may be equal where l1 and l2 were different, though).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 1
    In other words: it's guaranteed that if L1>L2, then F1>=F2 – mcleod_ideafix Dec 17 '13 at 17:25
  • If both variables in fact get converted to `float`, that would be true. I think implementations may vary with regard to e.g. `float f1 = l1; if (f1 < l2)...`, since `l2` might get converted to `float`, but I don't think it would necessarily have to be. Even with `float f1=l1; float f2=l2;` I'm not sure some implementations (especially with a "sloppy math" option enabled) might not keep one variable in RAM as a 32-bit float while keeping the other in a 64-bit float register. – supercat Dec 17 '13 at 18:35
  • @supercat A C99 compiler that implements IEEE 754 and rightfully defines FLT_EVAL_METHOD to 0, 1 or 2 should produce the expect result, since both the `(float)` cast and the assignment to `f1` and `f2` convert to the nominal type under these conditions. With a non-IEEE 754 compiler, or FLT_EVAL_METHOD<0, anything is theoretically possible. – Pascal Cuoq Dec 17 '13 at 19:59
  • @supercat Many compilers define `FLT_EVAL_METHOD` to 0, 1 or 2, but not rightfully so: older GCC versions (or recent versions without, say, `-std=c99`) generating 387 code. Clang generating 387 code. Most other compilers generating 387 code. I wrote up some experiments at http://blog.frama-c.com/index.php?post/2013/07/06/On-the-precise-analysis-of-C-programs-for-FLT_EVAL_METHOD-2 and http://blog.frama-c.com/index.php?post/2013/07/24/More-on-FLT_EVAL_METHOD_2 – Pascal Cuoq Dec 17 '13 at 20:02