443,617 Members | 1,792 Online
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,617 IT Pros & Developers. It's quick & easy.

# 12.34f vs (float) 12.34

 P: n/a Is there a difference between a constant like "12.34f" and "(float) 12.34"? In principle, at least, the latter is a double constant being cast to a float; while the two both generate actual constants, does the latter ACTUALLY do a conversion at compile time? That is, are there constants where f != (float) ? -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #1
19 Replies

 P: n/a No. The compiler will optimize the cast away assuming it can. It's probably generating something like this: private static void Blah() ..locals (float V_0, float V_1) L_0000: ldc.r4 1.23 L_0001: stloc.0 L_0002: ldc.r4 4.56 L_0003: stloc.1 from this: static void Blah() { float f1 = 1.23F; float f2 = (float) 4.56; } -- ____________________ Klaus H. Probst, MVP http://www.vbbox.com/ "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... Is there a difference between a constant like "12.34f" and "(float) 12.34"? In principle, at least, the latter is a double constant being cast to a float; while the two both generate actual constants, does the latter ACTUALLY do a conversion at compile time? That is, are there constants where f != (float) ? -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #2

 P: n/a "Klaus H. Probst" wrote: No. The compiler will optimize the cast away assuming it can. It's probably generating something like this: private static void Blah() .locals (float V_0, float V_1) L_0000: ldc.r4 1.23 L_0001: stloc.0 L_0002: ldc.r4 4.56 L_0003: stloc.1 from this: static void Blah() { float f1 = 1.23F; float f2 = (float) 4.56; } Indeed it is. The question, though, was HOW it's optimizing the cast away, whether code like "1.23f" and "(float) 1.23" might ever generate slightly different constants. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #3

 P: n/a The answers to those two questions are: HOW: it's called constant folding, and is performed by the C# compiler, and there's loads of information out there, and WHETHER: in theory I think they could in your example (but that's just my interpretation); section 11.1.3 of the CLI docs states: "Storage locations for floating point numbers (statics, array elements, and fields of classes) are of fixed size. The supported storage sizes are float32 and float64. Everywhere else (on the evaluation stack, as arguments, as return types, and as local variables) floating point numbers are represented using an internal floating-point type. In each such instance, the nominal type of the variable or expression is either R4 or R8, but its value may be represented internally with additional range and/or precision. The size of the internal floating-point representation is implementation-dependent, may vary, and shall have precision at least as great as that of the variable or expression being represented." From my experience the internal representation can differ between debug and release. Hope that helps, but please don't take my answer as gospel. Stu "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... "Klaus H. Probst" wrote: No. The compiler will optimize the cast away assuming it can. It's probably generating something like this: private static void Blah() .locals (float V_0, float V_1) L_0000: ldc.r4 1.23 L_0001: stloc.0 L_0002: ldc.r4 4.56 L_0003: stloc.1 from this: static void Blah() { float f1 = 1.23F; float f2 = (float) 4.56; } Indeed it is. The question, though, was HOW it's optimizing the cast away, whether code like "1.23f" and "(float) 1.23" might ever generate slightly different constants. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #4

 P: n/a Stu Smith wrote: HOW: it's called constant folding, Yes, thanks. Point of my question, though, is that I can imagine a few ways that this might be done: * Very straightforwardly, whereby "(float) 1.23" constructs a double value 1.23, then casts it to a single. * More convolutedly, whereby the constant folding operation sees the (float) cast being applied to an implicitly typed double, and goes back to the literal and reparses it as 1.23f. * Complex parsing, where cast followed by a literal parses the literal exactly as if it were 1.23f. The point being that in some cases the first approach might yield slightly different values than the first. WHETHER: in theory I think they could in your example (but that's just my interpretation); section 11.1.3 of the CLI docs states: I'm not sure that ECMA-335 has much to say about the workings of the compiler .... -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #5

 P: n/a "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... Stu Smith wrote: HOW: it's called constant folding, Yes, thanks. Point of my question, though, is that I can imagine a few ways that this might be done: * Very straightforwardly, whereby "(float) 1.23" constructs a double value 1.23, then casts it to a single. * More convolutedly, whereby the constant folding operation sees the (float) cast being applied to an implicitly typed double, and goes back to the literal and reparses it as 1.23f. * Complex parsing, where cast followed by a literal parses the literal exactly as if it were 1.23f. As far as I'm aware (and we're at the limits of my knowledge here), constant folding is done at compile time, so option one is out of the question. I believe the compiler makes passes over the statement/expression trees it has generated, looking for certain patterns, and replacing them with equivalents. I guess one pattern could be something like "(builtin value type) constant -> new constant". The point being that in some cases the first approach might yield slightly different values than the first. WHETHER: in theory I think they could in your example (but that's just my interpretation); section 11.1.3 of the CLI docs states: I'm not sure that ECMA-335 has much to say about the workings of the compiler .... Don't know about that, but I do know that if you have a variable of type float it's not guaranteed to be no more than a float. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #6

 P: n/a Stu Smith wrote: * Very straightforwardly, whereby "(float) 1.23" constructs a double value 1.23, then casts it to a single. As far as I'm aware (and we're at the limits of my knowledge here), constant folding is done at compile time, so option one is out of the question. We're pretty much at the limits of my knowledge, too. I've written a simple compiler, so I have some knowledge of the issues involved, but that's about it. But I don't see why you say that option 1 can be ruled out? Seems to me: Parser sees a stream of digits followed by a . and another stream of digits which is NOT followed by one of {d, f, m}. Bingo: a double constant for the parse tree. Optimizer later comes along and sees the expression cast(float, double constant) and does a compile-time cast, reducing it to a float constant. * * * I suppose I should just do the brute force thing: write a simple test program to generate reams of float constants, and see if (say) 2.22222222222222f != (float) 2.22222222222222. Course, I'll probably find more than I care to know about method size limits .... -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #7

 P: n/a "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... Stu Smith wrote: * Very straightforwardly, whereby "(float) 1.23" constructs a double value 1.23, then casts it to a single. As far as I'm aware (and we're at the limits of my knowledge here), constant folding is done at compile time, so option one is out of the question. We're pretty much at the limits of my knowledge, too. I've written a simple compiler, so I have some knowledge of the issues involved, but that's about it. But I don't see why you say that option 1 can be ruled out? Seems to me: Parser sees a stream of digits followed by a . and another stream of digits which is NOT followed by one of {d, f, m}. Bingo: a double constant for the parse tree. Optimizer later comes along and sees the expression cast(float, double constant) and does a compile-time cast, reducing it to a float constant. I thought you meant a run-time cast. Not sure whether you'd call compile-time folding a cast but I think we're talking the same thing, even if we use different words. * * * I suppose I should just do the brute force thing: write a simple test program to generate reams of float constants, and see if (say) 2.22222222222222f != (float) 2.22222222222222. And what I meant about having extra precision was something like this: class Foo { public void Test() { float localFloat = _memberFloat; // The following doesn't have to be true, ie assertion could fire. Debug.Assert( _memberFloat == localFloat ); } private float _memberFloat = 1.23; } Course, I'll probably find more than I care to know about method size limits .... -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 15 '05 #8

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #9

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #10

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #11

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #12

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #13

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #14

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #15

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #16

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #17

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #18

 P: n/a cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #19

 P: n/a The C# compiler will act the same way on ALL platforms. The JIT will not. The MSIL should be all the same regardless of the CPU or the OS you're compiling under. About the conversion - you can check out what does the C# compiler spits out with the ILDASM utility. Located in the .NET Framework SDK folder. Cheers, Branimir -- Branimir Giurov MCSD.NET, MCDBA eAgility LLC "Jon Shemitz" wrote in message news:40***************@midnightbeach.com... cody wrote: Is there a difference between a constant like "12.34f" and "(float) 12.34"? You can be sure that both are evaluated to compile time contants (at least jit time). But you cannot assume that 12.34f ==(float)12.34 because conversion double to float might result in loss of precision. Right. This is pretty much where I ended up. Even if the canonical (MS) C# compiler works this way on a Pentium, that is not to say that all C# compilers on all processors will act this way. -- programmer, author http://www.midnightbeach.com and father http://www.midnightbeach.com/hs Nov 16 '05 #20

### This discussion thread is closed

Replies have been disabled for this discussion.