Should we generally use float literals for floats instead of the simpler double literals?
Should we generally use float literals for floats instead of the simpler double literals?
In C++ (or maybe only our compilers VC8 and VC10) 3.14
is a double literal and 3.14f
is a float literal.
Now I have a colleague that stated:
We should use float-literals for float calculations and double-literals for double calculations as this could have an impact on the precision of a calculation when constants are used in a calcualtion.
Specifically, I think he meant:
double d1, d2; float f1, f2; ... init and stuff ... f1 = 3.1415 * f2; f1 = 3.1415f * f2; // any difference? d1 = 3.1415 * d2; d1 = 3.1415f * d2; // any difference?
Or, added by me, even:
d1 = 42 * d2; d1 = 42.0f * d2; // any difference? d1 = 42.0 * d2; // any difference?
More generally, the only point I can see for using 2.71828183f
is to make sure that the constant I'm trying to specify will actually fit into a float (compiler error/warning otherwise).
Can someone shed some light on this? Do you specify the f
postfix? Why?
To quote from an answer what I implicitly took for granted:
If you're working with a float variable and a double literal the whole operation will be done as double and then converted back to float.
Could there possibly be any harm in this? (Other than a very, very theoretical performance impact?)
Further edit: It would be nice if answers containing technical details (appreciated!) could also include how these differences affect general purpose code. (Yes, if you're number crunching, you probably like to make sure your big-n floating point ops are as efficient (and correct) as possible -- but does it matter for general purpose code that's called a few times? Isn't it cleaner if the code just uses 0.0
and skips the -- hard to maintain! -- float suffix?)
Answer by thiton for Should we generally use float literals for floats instead of the simpler double literals?
There is a difference: If you use a double constant and multiply it with a float variable, the variable is converted into double first, the calculation is done in double, and then the result is converted into float. While precision isn't really a problem here, this might lead to confusion.
Answer by Mark B for Should we generally use float literals for floats instead of the simpler double literals?
I suspect something like this: If you're working with a float variable and a double literal the whole operation will be done as double and then converted back to float.
If you use a float literal, notionally speaking the computation will be done at float precision even though some hardware will convert it to double anyway to do the calculation.
Answer by Martin for Should we generally use float literals for floats instead of the simpler double literals?
I personally tend to use the f postfix notation as a matter of principles and to make it obvious as much as I can that this is a float type rather than a double.
My two cents
Answer by Andrew Marshall for Should we generally use float literals for floats instead of the simpler double literals?
From the C++ Standard ( Working Draft ), section 5 on binary operators
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are de?ned as follows: ? If either operand is of scoped enumeration type (7.2), no conversions are performed; if the other operand does not have the same type, the expression is ill-formed. ? If either operand is of type long double, the other shall be converted to long double. ? Otherwise, if either operand is double, the other shall be converted to double. ? Otherwise, if either operand is float, the other shall be converted to float.
And also section 4.8
A prvalue of ?oating point type can be converted to a prvalue of another ?oating point type. If the source value can be exactly represented in the destination type, the result of the conversion is that exact representation. If the source value is between two adjacent destination values, the result of the conversion is an implementation-de?ned choice of either of those values. Otherwise, the behavior is unde?ned
The upshot of this is that you can avoid unnecessary conversions by specifying your constants in the precision dictated by the destination type, provided that you will not lose precision in the calculation by doing so (ie, your operands are exactly representable in the precision of the destination type ).
Answer by James Kanze for Should we generally use float literals for floats instead of the simpler double literals?
Typically, I don't think it will make any difference, but it is worth pointing out that 3.1415f
and 3.1415
are (typically) not equal. On the other hand, you don't normally do any calculations in float
anyway, at least on the usual platforms. (double
is just as fast, if not faster.) About the only time you should see float
is when there are large arrays, and even then, all of the calculations will typically be done in double
.
Answer by Stephen Canon for Should we generally use float literals for floats instead of the simpler double literals?
Yes, you should use the f
suffix. Reasons include:
Performance. When you write
float foo(float x) { return x*3.14; }
, you force the compiler to emit code that converts x to double, then does the multiplication, then converts the result back to single. If you add thef
suffix, then both conversions are eliminated. On many platforms, each those conversions are about as expensive as the multiplication itself.Performance (continued). There are platforms (most cellphones, for example), on which double-precision arithmetic is dramatically slower than single-precision. Even ignoring the conversion overhead (covered in 1.), every time you force a computation to be evaluated in double, you slow your program down. This is not just a "theoretical" issue.
Reduce your exposure to bugs. Consider the example
float x = 1.2; if (x == 1.2) // something;
Issomething
executed? No, it is not, because x holds1.2
rounded to afloat
, but is being compared to the double-precision value1.2
. The two are not equal.
Answer by Vaughn Cato for Should we generally use float literals for floats instead of the simpler double literals?
I did a test.
I compiled this code:
float f1(float x) { return x*3.14; } float f2(float x) { return x*3.14F; }
Using gcc 4.5.1 for i686 with optimization -O2.
This was the assembly code generated for f1:
pushl %ebp movl %esp, %ebp subl $4, %esp # Allocate 4 bytes on the stack fldl .LC0 # Load a double-precision floating point constant fmuls 8(%ebp) # Multiply by parameter fstps -4(%ebp) # Store single-precision result on the stack flds -4(%ebp) # Load single-precision result from the stack leave ret
And this is the assembly code generated for f2:
pushl %ebp flds .LC2 # Load a single-precision floating point constant movl %esp, %ebp fmuls 8(%ebp) # Multiply by parameter popl %ebp ret
So the interesting thing is that for f1, the compiler stored the value and re-loaded it just to make sure that the result was truncated to single-precision.
If we use the -ffast-math option, then this difference is significantly reduced:
pushl %ebp fldl .LC0 # Load double-precision constant movl %esp, %ebp fmuls 8(%ebp) # multiply by parameter popl %ebp ret pushl %ebp flds .LC2 # Load single-precision constant movl %esp, %ebp fmuls 8(%ebp) # multiply by parameter popl %ebp ret
But there is still the difference between loading a single or double precision constant.
Update for 64-bit
These are the results with gcc 5.2.1 for x86-64 with optimization -O2:
f1:
cvtss2sd %xmm0, %xmm0 # Convert arg to double precision mulsd .LC0(%rip), %xmm0 # Double-precision multiply cvtsd2ss %xmm0, %xmm0 # Convert to single-precision ret
f2:
mulss .LC2(%rip), %xmm0 # Single-precision multiply ret
With -ffast-math, the results are the same.
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment