65

What is the difference between

float f = (float) 99.32 ;

and

float f = 99.32f ;

Both of them compiled and ran successfully.

Eric Stein
  • 13,209
  • 3
  • 37
  • 52
  • 15
    The first suffers from [double rounding error](http://www.exploringbinary.com/double-rounding-errors-in-floating-point-conversions/), which is not good as the result might not be the desired value. The second one produces a correctly rounded float value https://en.wikipedia.org/wiki/Rounding#Double_rounding – phuclv Oct 16 '15 at 08:15
  • That link uses way too long a representation of its example number. "0.50000008940696713" is sufficient. – Random832 Oct 16 '15 at 16:13
  • @LưuVĩnhPhúc: I expect it used a precise decimal representation of a value halfway between two adjacent double values, though I would suggest that adding a large integer to the value would make precise decimal representations much shorter and more obvious. – supercat Oct 16 '15 at 19:09
  • 1. Do you mean, for that decimal string specifically, or for any one? 2. What does "successfully" mean? "Returned the same value"? (Do they test as equal? Did you examine the *entire* representation?) – philipxy Oct 21 '15 at 08:38

6 Answers6

88
float f = 99.32f ;

That is a float literal, which means a float variable being assigned with a float value directly.

float f = (float) 99.32 ;

That is a float variable that is assigned a double value that is cast to float before being assigned.

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
Magisch
  • 7,312
  • 9
  • 36
  • 52
  • 6
    Would the compiler optimize this out? (in the cast case) – Austi01101110 Oct 16 '15 at 07:12
  • @Austi01101110 Depends on the compiler, and what you later do with it. Not in all compilers is that equivalent in assembly code. If you use the second option you get 2x rounding, once when casting to a double, another time when casting to float. – Magisch Oct 16 '15 at 07:13
  • 1
    Where is a cast to `double`? – mch Oct 16 '15 at 07:53
  • `99.32` without f is an implied cast to a double. – Magisch Oct 16 '15 at 07:54
  • 16
    no, `99.32` is a floating point literal, which has the type `double`. – mch Oct 16 '15 at 08:14
  • So you are casting the value `99.32` to a `double` by declaring it a floating point literal of default type `double`. In this case the decimal representation is rounded to a `double`, and then again to a float by the explicit cast, whilst in the first example float `f = 99.32f ;` the decimal value is beeing directly cast to a `float` – Magisch Oct 16 '15 at 08:17
  • 22
    no, `99.32` is a `double`, not implicit casted to it. This is called "floating point literal of type `double`". `99.32f` is a `float` and not casted to it. This is called "floating point literal of type `float`". There is no cast at `float f = 99.32f;` or `double d = 99.32;`. – mch Oct 16 '15 at 08:23
  • 2
    Maybe im using the word "cast" wrong. I mean that by the second method, you are assigning the decimal value `99.32` as a double, subjecting it to the initial rounding for a double. When you then cast to a `float`, you subject it again to the initial rounding of a float. – Magisch Oct 16 '15 at 08:26
  • 4
    @Magisch: That's correct. Earlier you were suggesting that simply writing a literal involves a cast, which is incorrect. – Lightness Races in Orbit Oct 16 '15 at 11:37
  • 1
    @mch The only point here is that `99.32` is a representation of a number in decimal notation and whatever technically correct word you prefer use for converting/casting/whatever it by the compiler into a `double` (normally a binary notation internally), that operation might lose precision. – Eugene Ryabtsev Oct 16 '15 at 11:46
  • 3
    @EugeneRyabtsev That's true, but that's not complete. The five-character `99.32` literal is by default converted by a compiler to a `double` type representation; this is one convertion. Then explicit `(float)` cast causes another convertion from `double` type to `float`. And the final result *may* differ from a one-step conversion from a 6-characters literal `99.32f` to a `float` type representation. – CiaPan Oct 16 '15 at 13:30
  • 8
    Is there any difference in value between the two? – John Dvorak Oct 16 '15 at 13:53
  • @Austi01101110 The compiler might optimize out the cost of doing a runtime conversion, but that doesn't mean it would give the same value. – Random832 Oct 16 '15 at 15:49
  • 6
    @JanDvorak: Rare, and likely not in this case. (float) 99.32 is the real number 99.32, rounded to the nearest available double number, rounded to the nearest available float number. 99.32f is the real number 99.32, rounded to the nearest float number. Let x be a number that is exactly halfway between two neighbouring float numbers. Let d and d' be two decimal numbers that is just a tiny tiny bit larger/smaller than x. Then the .f suffix would be rounded up/down, but rounding to double might give the result x in both cases, and casting to float will round either d or d' in the wrong direction. – gnasher729 Oct 16 '15 at 22:41
  • 2
    @gnasher729 An excellent observation. I think you should make it into an answer, perhaps. Maybe when I have time I will try to find a "nice" (i.e. not too many decimal digits in the source code literal) example where rounding to nearest `double` followed by rounding to nearest `float` gives something different from doing just one round to `float`. – Jeppe Stig Nielsen Oct 17 '15 at 01:02
  • @gnasher729 Can You Tell Me Difference Between float f = 99.32 and float f = (float)99.32 – Suraj Jain Apr 03 '17 at 02:27
  • @BoundaryImposition Deleted – Suraj Jain Apr 03 '17 at 02:27
  • @SurajJain: You deleted your comments then just repeated your original comment, now to somebody else. _If you have a new question, post a new question._ I don't know how to be any clearer about this, Suraj. – Lightness Races in Orbit Apr 03 '17 at 08:42
  • @SurajJain This has been answered here a dozen times or more already. Simply put, `f = 99,32` is an implicit cast and `float f = (float) 99.32` is an explicit cast. Search for what both mean on google. – Magisch Apr 03 '17 at 08:50
  • @Magisch Does It Makes Any Difference, That is why i am asking. – Suraj Jain Apr 03 '17 at 10:45
  • @SurajJain It depends. Depends on your compiler, depends on your optimization level, depends on the precision you need, on your specific use case. I can't give you a definitive answer on that. – Magisch Apr 03 '17 at 10:50
  • @Magisch Can We Have Chat? – Suraj Jain Apr 03 '17 at 10:57
25

The difference may be optimized away, but in the first case you have a double literal that is type casted to a float while you have a float literal in the second case.

If not optimized away you will get a typecast in the code in the second example.

However there are corner cases where the result could (depending on rounding mode) be slightly different. If your number can't be exactly represented you will in the first case get rounding twice - first when you round the decimal representation to a double and then when you round that to a float, while in the first case you round the decimal representation directly to a float.

skyking
  • 13,817
  • 1
  • 35
  • 57
  • Since an ULP in single-precision is so much larger than an ULP in double precision, I find it hard to believe the doubled rounding could have a significant effect. – Kevin Oct 16 '15 at 13:31
  • "However there are corner cases where the result could (depending on rounding mode) be slightly different." - examples? – John Dvorak Oct 16 '15 at 13:53
  • 1
    @Kevin It would have an effect of up to one _float_ ULP difference. – John Dvorak Oct 16 '15 at 13:54
  • 1
    I suspect a corner case does exist, but have not found it. – chux - Reinstate Monica Oct 16 '15 at 15:18
  • 11
    0.50000008940696713 yields a different result: with rounding you get `0x1.000004p-1` while with suffix you get `0x1.000002p-1` (see http://ideone.com/EV3QeG). See also https://en.wikipedia.org/wiki/Rounding#Double_rounding – Matthieu M. Oct 16 '15 at 17:59
  • 2
    More specifically, last two digits of 11-21 all result in `0x1.000003p-1` as double (and therefore `0x1.000004p-1` when double-rounded to float), and last two digits of 11-16 (roughly half of this range) result in `0x1.000002p-1`. So the range of values over which this can occur (for each instance, presumably spaced one float ULP apart) is roughly one half of one double ULP wide, and in every case yields an "error" of one half of one float ULP when rounded up or down, since the real values are roughly halfway between two float values. – Random832 Oct 16 '15 at 18:36
  • @JanDvorak: It can mean the difference between a float which is about .500000001 way from the specified value and one which is .499999999 away. In most cases where it would matter which result is chosen, one should use a double representation that's not almost half an ulp away from the desired float. – supercat Oct 16 '15 at 19:13
11

In the first case without the cast 99.32 is interpreted as double not as a float.

A double literal is being casted to float.

In the second case you have a suffix f to make sure the compiler treats 99.32 as float.

Gopi
  • 19,784
  • 4
  • 24
  • 36
11

In the line float f = (float) 99.32; the literal 99.32 is created as a double type by default and is then cast to a float.

In the line float f = 99.32f ; the literal is created as a float type due to the trailing f in 99.32f and no type casting is required.

The latter would be analogous to writing double f = 99.32; as you'd have a double type being assigned directly to a variable of a matching type.

code_dredd
  • 5,915
  • 1
  • 25
  • 53
10

Floating point literals without a suffix are by default of double type.

Thus, stating float f = (float) 99.32; you first cast explicitly literal 99.32 which is of type double to a float and then assign it to variable f.

Stating float f = 99.32; does the same thing but in this case the conversion between types is done implicitly.

If you want to avoid implicit conversion you should use the f suffix to define your literal (i.e., float f = 99.32f;)

101010
  • 41,839
  • 11
  • 94
  • 168
  • no they're not the same thing, [without the `f` suffix the result is sometimes wrong](https://stackoverflow.com/a/68586856/995714) – phuclv Apr 17 '22 at 10:32
6

The difference is that the literal 99.32 is of type double, while the literal 99.32f is of type float.

The first statement assigns the float literal to a float variable. Nothing special.

The second statement casts a double literal to a float, and assigns the result to a float variable.

As far as the standard is concerned, you can assign a double literal to a float variable, without explicitly casting it yourself. In that case implicit cast occurs. E.g. :

float f = 99.32;

You can even do :

float f = (double) 10.5f;

and the right hand side is still implicitly converted to a float.

Please note that most modern compilers optimize those away, so representing floats is usually matter of style and preference. Just be consistent.

Evdzhan Mustafa
  • 3,645
  • 1
  • 24
  • 40
  • This's wrong, **they're not purely for consistency** but they're required for accuracy. [Without the `f` suffix the result is sometimes wrong](https://stackoverflow.com/a/68586856/995714). Always use `f` for `float` and `L` for `long double` – phuclv Apr 17 '22 at 10:33