Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 算术是交换的和结合的吗?_C#_.net_Math - Fatal编程技术网

C# 算术是交换的和结合的吗?

C# 算术是交换的和结合的吗?,c#,.net,math,C#,.net,Math,在数学中,(实数的)加法是交换的和结合的,即对于所有的数x、y和z x+y=y+x(交换性) 及 x+(y+z)=(x+y)+z(结合性) 实数乘法也是交换的和结合的。但是对于.NET中的int和float,这是真的吗?欢迎反例 编辑:背景是我们最近并行了一个算法,现在它的结果在重复之间不再一致。我推测这可能是由于原子计算以不确定的顺序返回(并被合并)。在这种情况下,可以通过更智能(但速度较慢)的合并算法(在合并前对结果进行排序)来修复不一致性。我想知道它能对.NET算术做出什么样的假设 对于i

在数学中,(实数的)加法是交换的和结合的,即对于所有的数x、y和z

x+y=y+x(交换性)

x+(y+z)=(x+y)+z(结合性)

实数乘法也是交换的和结合的。但是对于.NET中的int和float,这是真的吗?欢迎反例


编辑:背景是我们最近并行了一个算法,现在它的结果在重复之间不再一致。我推测这可能是由于原子计算以不确定的顺序返回(并被合并)。在这种情况下,可以通过更智能(但速度较慢)的合并算法(在合并前对结果进行排序)来修复不一致性。我想知道它能对.NET算术做出什么样的假设

对于
int
是,对于(不幸的选择)
float
(由于精度有限)。

假设没有未检查的溢出发生,.NET的整数加法和乘法(
int
long
等)是可交换和关联的,就像数学中的实数一样。浮点运算(
float
double
)是可交换的,但由于精度的限制,并不总是精确关联的。发件人:

虽然浮点加法和乘法都是可交换的(a+b=b+a和a×b=b×a),但它们不一定是关联的。也就是说,(a+b)+c不一定等于a+(b+c)

下面是一个例子:

a: 0.825402526103613
b: 0.909231618470155
c: 0.654626872695343
(a*b)*c: 0.491285733573819
a*(b*c): 0.49128573357382
在一些示例中,当转换为
字符串时,结果显示相同,但不同(
(a*b)*c!=a*(b*c)
,而
(a*b)*c-a*(b*c)
返回一个小值,而不是
0


在并行简化中:

floats.AsParallel().Sum();
。。。每次你都可以期待不同的结果。这是因为每次工作的分区都不同,这在添加数字时会导致不同的舍入错误

为了最大限度地减少此问题,请确保减少是使用双精度,而不是浮点数。如果您希望按位获得相同的结果,则不应使用TPL或PLINQ,而应使用自己的并行计算

请注意,在C++中,FP精度不能像C++那样严格保证。阅读Eric对

的回答,在未检查的上下文中(默认情况下),溢出的存在与关联性和交换性无关

例如,以
0x7fffffff+0x8000000+0xffffffff
为例。结果是
0xfffffffe
(aka-2),无论您如何将其插入括号。但是
(0x7fffffff+0x8000000)+0xFFFFFF
不会溢出,而
0x7fffffff+(0x8000000+0xFFFFFF)
会溢出两次。(在无符号算术中,它们都会溢出一次)


一般来说,情况也是如此。在C#(如果
未选中
)和Java中的整数中。在C和C++中,这仅仅保证了无符号整数,因为符号溢出是未定义的。

dv似乎有点极端,但是你到底想解决什么问题?坚持“我不知道我在说什么,但是我会说出我对这个问题的看法”,我想它对整数是成立的。但不一定是浮点数。至少这是我对浮点运算的直觉。在任何语言中,基本的数学规则都是受尊重的。当然,对于整数,交换性、结合性以及加法的置换性都应该在数值舍入精度的限制范围内得到尊重。同样,您关于并行化(我假设是多线程)的评论可能表明了一个完全不同的问题。也许您有一个竞争条件或非原子操作需要更好的锁定。而且,
int
s可以进行溢出检查。@millimoose:如果溢出导致异常,那么,是的,这将破坏一切。如果它们只是“滚动”,那么应用程序的顺序就不重要了。在C#中,滚动是默认的IIRC。(当然与OP没有特别关系,但仍然如此。)未经检查的溢出实际上不会破坏交换性或结合性(对于整数,浮点是另一回事)。不过,检查过的溢出是可以的。
floats.AsParallel().Sum();