繁体   English   中英

UInt64整数较大的产品的模数不正确

[英]The modulus of a product with a large UInt64 integer is incorrect

为什么最后一条输出线返回51? 第一行证明mod b为零。 我希望第三行也为零,因为我只是将数字乘以相同的B。

没有异常被抛出。 我认为这是一个溢出,但是为什么呢? 以及如何避免这种情况?

UInt64 A = 749243140505953395;
UInt64 B = 71;

Console.WriteLine((A % B) == 0);
Console.WriteLine((A*B) < UInt64.MaxValue); 
Console.WriteLine((A * B) % B);

C#是一种很好的语言,几乎没有未定义的行为。 但是,您在这里看到的只是一个非常错误的值。 相当可悲的是,这种故障模式非常容易避免。 微软严重搞砸了他们的项目模板。

但是,您无法解决任何问题。 确保选择了Debug配置,然后使用Project> Properties> Build选项卡> Advanced按钮>选中“检查算术上溢/下溢”选项。 再次运行程序,您将获得:

Example.exe中发生了'System.OverflowException'类型的未处理异常
附加信息:算术运算导致溢出。

如果您对代码有足够的信心,则可以为Release版本关闭该选项,溢出检查非常昂贵。 加或纳秒。 不必担心您在Debug版本中会花费多少。

由于以下原因,最后一条输出行返回51。

首先,A * B导致64位无符号整数溢出。 这就是为什么。 71 * 749243140505953395 = 53196262975922691045此乘积大于UInt64.MaxValue,它等于18446744073709551615

根据C#语言规范,在未经检查的上下文中,溢出将被忽略,并且不适合目标类型的所有高阶位都将被丢弃。 因此,将53196262975922691045(十六进制2 E2 3F 17 54 AA 22 DB E5)变成E2 3F 17 54 AA 22 DB E5(在对高阶位进行修整后,二进制的前十六进制“ 2”或“ 10”将被丢弃)。 供您参考,目标类型的64位无符号整数的最大值(十六进制)为FF FF FF FF FF FF FF FF FF

修剪转换为十进制的高阶位(E2 3F 17 54 AA 22 DB E5)后的十六进制为16302774828503587813。修剪后的数字由无符号的64位整数表示,而不会引起溢出。

最后16302774828503587813%71 = 51

顺便提一句,正如@EZI刚指出的那样,对于很大的整数,最好使用BigInteger结构。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM