C++: difference between 0. and 0.0?
There is no difference. Both literals are double. From the C++-Grammar:
fractional-constant:
digit-sequenceopt . digit-sequence
digit-sequence .
See: Hyperlinked C++ BNF Grammar
What is the significance of 0.0f when initializing (in C)?
float x = 0 has an implicit typecast from int to float.
float x = 0.0f does not have such a typecast.
float x = 0.0 has an implicit typecast from double to float.
Depending on the compiler, implicit typecast can require the compiler to generate extra code.
What operations and functions on +0.0 and -0.0 give different arithmetic results?
There are a few standard operations and functions that form numerically different answers between f(+0.0)
and f(-0.0)
.
Different rounding modes or other floating point implementations may give different results.
#include <math.h>
double inverse(double x) { return 1/x; }
double atan2m1(double y) { return atan2(y, -1.0); }
double sprintf_d(double x) {
char buf[20];
// sprintf(buf, "%+f", x); Changed to e
sprintf(buf, "%+e", x);
return buf[0]; // returns `+` or `-`
}
double copysign_1(double x) { return copysign(1.0, x); }
double signbit_d(double x) {
int sign = signbit(x); // my compile returns 0 or INT_MIN
return sign;
}
double pow_m1(double x) { return pow(x, -1.0); }
void zero_test(const char *name, double (*f)(double)) {
double fzp = (f)(+0.0);
double fzn = (f)(-0.0);
int differ = fzp != fzn;
if (fzp != fzp && fzn != fzn) differ = 0; // if both NAN
printf("%-15s f(+0):%-+15e %s f(-0):%-+15e\n",
name, fzp, differ ? "!=" : "==", fzn);
}
void zero_tests(void) {
zero_test("1/x", inverse);
zero_test("atan2(x,-1)", atan2m1);
zero_test("printf(\"%+e\")", sprintf_d);
zero_test("copysign(x,1)", copysign_1);
zero_test("signbit()", signbit_d);
zero_test("pow(x,-odd)", pow_m1);; // @Pascal Cuoq
zero_test("tgamma(x)", tgamma); // @vinc17 @Pascal Cuoq
}
Output:
1/x f(+0):+inf != f(-0):-inf
atan2(x,-1) f(+0):+3.141593e+00 != f(-0):-3.141593e+00
printf("%+e") f(+0):+4.300000e+01 != f(-0):+4.500000e+01
copysign(x,1) f(+0):+1.000000e+00 != f(-0):-1.000000e+00
signbit() f(+0):+0.000000e+00 != f(-0):-2.147484e+09
pow(x,-odd) f(+0):+inf != f(-0):-inf
tgamma(x) f(+0):+inf != f(-0):+inf
Notes:tgamma(x)
came up ==
on my gcc 4.8.2 machine, but correctly !=
on others.
rsqrt()
, AKA 1/sqrt()
is a maybe future C standard function. May/may not also work.
double zero = +0.0; memcpy(&zero, &x, sizeof x)
can show x
is a different bit pattern than +0.0
but x
could still be a +0.0
. I think some FP formats have many bit patterns that are +0.0
and -0.0
. TBD.
This is a self-answer as provided by https://stackoverflow.com/help/self-answer.
any difference between x=0 and x=0.0 for a double x variable? c code
In practice, there doesn't have to be any difference although there is an implicit conversion in the first case since 0
is an int
.
I tried it (on assembly.ynh.io). This C code:
#include <stdio.h>
int main(void)
{
double x, y;
x = 0;
y = 0.;
printf("x=%g and y=%g\n", x, y);
return 0;
}
generated the following assembly for the two assignments (to x
and y
):
0008 B8000000 00 movl $0, %eax
000d 488945F0 movq %rax, -16(%rbp)
0011 B8000000 00 movl $0, %eax
0016 488945F8 movq %rax, -8(%rbp)
In other words, the code is exactly the same. This was built by GCC, without optimization.
I guess this takes advantage of the fact that the bitpatterns are all zero in both cases.
0 vs 0.0 in conditional statements
double a = 0.0000000000001;
int b = 0;
res = a <= b; // False
res2 = b >= a; // False
Given the above test, I'd say C# opts for the least lossy conversion. (Not a preference for left or right side)
So to answer your question, no. There isn't a difference.
Why is C++ implicitly converting 0.0 to some extremly small 'random' value?
Your Vector
class never initializes the x
and y
members.
Since the member variables are uninitialized, they will have an indeterminate value, which you should look at like it was random or garbage. Using indeterminate values of any kind in any way, leads to undefined behavior.
To initialize the member variables, use a constructor initializer list:
Vector(double x = 0.0, double y = 0.0)
: x{ x }, y{ y }
{
}
On another note, floating point arithmetic on a computer will lead to rounding errors. The more operations you perform, the larger the error will be. And sooner or later you will think that floating point math is broken.
All this rounding of course means that it's almost impossible to do exact comparisons of floating point values.
The common way is to use an epsilon, a small margin of error, for your comparisons.
Related Topics
Assert That Code Does Not Compile
What Does the "::" Mean in "::Tolower"
What Is the Meaning of Double Curly Braces Initializing a C-Struct
Stl Vectors with Uninitialized Storage
Why Does C++ Allow Private Members to Be Modified Using This Approach
How to Read from Memory Just Like from a File Using iOStream
Create Shared_Ptr to Stack Object
With C++, I Get Pointer with 0Xcdcdcdcd When Creating a Class - What Is Happening
Is It Legal to Cast a Pointer to Array Reference Using Static_Cast in C++
Why Class Size Depend Only on Data Members and Not on Member Functions
Constexpr Not Working If the Function Is Declared Inside Class Scope
Why Is Std::Cout So Time Consuming
Unit Test That a Class Is Non Copyable, and Other Compile-Time Properties
Const and Non Const Template Specialization
C++. Error: Void Is Not a Pointer-To-Object Type
Are Non Dereferenced Iterators Past the "One Past-The-End" Iterator of an Array Undefined Behavior