对于一个非常简单的问题,我找不到清晰,简单的答案!我将问题分为两个版本。
在C#中,假设我运行以下命令:
double x = 76239.78362194721;
double y = -3;
y = x; // copied by value, as doubles are literals
//y = y + 1.4; // Version 1 of my question has these commented-out
//x = x + 1.4; // Version 2 of my question has these not commented-out
bool b = (x == y);
布尔值b
总是是真的吗?也就是说,尽管双精度之间的相等性度量不准确,但是计算机永远不会故意添加噪音吗?
b
能否取决于我要问的是版本1还是版本2? (我们可以假设x
和y
不是接近double的最大值或最小值,也不接近ε的正负值。
谢谢! 〜格雷格
答案 0 :(得分:-1)
使用y = x;
复制不会造成任何精度损失。
分配后,x == y
为真。
由于x
和y
相等,因此
y = y + 1.4;
x = x + 1.4;
x == y
很可能是正确的;但是,正如埃里克·利珀特(Eric Lippert)指出的那样(请参见下面的评论),这不能保证。
始终将双精度与所需精度进行比较:
const double Eps = 1e-10;
if (Math.Abs(x - y) < Eps) {
// x and y are equal enough
} else {
// x and y are not equal
}
当然,如果您仅注释掉其中之一,则x
和y
将相差约1.4
。它们可能相差1.399999999999999
或1.400000000000001
左右。如果两者都很大(例如1.0e25
),则加法将无效,因为它将影响被截断的小数。 double
的精度为15到16位数字。如果两者都很小(例如1.0e-25
),也是如此,因为这样它们的原始值将丢失,结果将是1.4
。
在“ C#交互式”窗口中,您可以进行测试
> 1e+25 + 1.4 == 1e+25
true
那
> 1e-25 + 1.4 == 1.4
true
...按值复制,因为双精度为文字
嗯,不完全是。 System.Double
(C#别名double
)是值类型。 3.141592654
是double
文字。在double x;
中,标识符x
是一个double
变量(如果在类型级别声明,则为字段)。
但是即使您复制...
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.
...变量的值按值复制。区别在于此值是参考。该值不是人员对象,而是对其的引用。
p2.Name = "Mark";
现在p1.Name == "Mark"
是正确的,但是p1
的值没有改变。它仍然是相同的参考。引用的对象确实发生了变化。
double d1 = 5;
double d2 = d1;
d2 = 77;
d1
仍为5。由于double
是值类型,因此变量直接包含数字。不涉及任何参考。
在另一个示例中,引用是通过引用传递的
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.
}
调用此方法后,p1
将包含个人Sue。
您可以有四种情况:(1)通过值传递的值类型。 (2)通过引用传递的值类型。 (3)按值传递的引用类型。 (4)通过引用传递的引用类型。