Copying with y = x;
does not cause any precision loss.
After the assignment, x == y
is true.
Since x
and y
are equal, after
y = y + 1.4;
x = x + 1.4;
x == y
is most likely true; however, as Eric Lippert pointed out (see comments below), this is not guaranteed.
Always compare doubles with a desired precision:
const double Eps = 1e-10;
if (Math.Abs(x - y) < Eps) {
// x and y are equal enough
} else {
// x and y are not equal
}
Of course, if you comment out only one of these, x
and y
will differ by approximately 1.4
. They might differ by 1.399999999999999
or 1.400000000000001
or so. If both are very big (e.g. 1.0e25
) the addition will have no effect, as it would affect decimals that are truncated. double
has a precision of 15-16 digits. The same is true, if both are very small (e.g. 1.0e-25
), because then their original values will be lost and the result will be 1.4
.
In the C# Interactive window you can test that
> 1e+25 + 1.4 == 1e+25
true
and that
> 1e-25 + 1.4 == 1.4
true
... copied by value, as doubles are literals
Well, not quite. System.Double
(C# alias double
) is a value type. 3.141592654
is a double
literal. In double x;
the identifier x
is a double
variable (or field if it is declared at the type level).
But even if you copy ...
var p1 = new Person { Name = "John" }; // Where Person is a class.
var p2 = p1;
// Now, p1 and p2 reference the same object. I.e. they have the same value.
... the value of the variable is copied by value. The difference is that this value is a reference. The value is not a person object but a reference to it.
p2.Name = "Mark";
Now p1.Name == "Mark"
is true, but the value of p1
did not change. It is still the same reference. The referenced object did change.
double d1 = 5;
double d2 = d1;
d2 = 77;
d1
is still 5. Because double
is a value type, the variables contain the numbers directly. No references are involved.
In this other example the reference is passed by reference
var p1 = new Person{ Name = "John" };
AssignAnotherPerson(ref p1);
void AssignAnotherPerson(ref Person p)
{
p = new Person{ Name = "Sue" }; // Here p is an alias for p1.
}
After this method is called, p1
will contain the person Sue.
You can have four cases: (1) A value type passed by value. (2) A value type passed by reference. (3) A reference type passed by value. (4) A reference type passed by reference.