簡體   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