[英]Two uint64_t numbers multiplication and division on coefficient in the C program are wrong compiled with GCC
[英]Computing determinant and using division and multiplication of uint64_t C type
該問題已被編輯以澄清它。
我有以下矩陣,定義在[reteam.org/papers/e59.pdf]的第1頁中,使用R表示法編寫:
m1 = matrix(c(207560540,956631177,1,956631177,2037688522,1,2037688522,1509348670,1),ncol=3,byrow=T)
m1的行列式應為2 ^ 31 -1的整數倍。
如接受的答案所示,det(m1)應該為-1564448852668574749。
但是,在R中,我得到了
> det(m1)
[1] -1564448852668573184
並通過手動使用一個簡單方程式:
> m1[1,1]*(m1[2,2]-m1[3,2]) - m1[2,1]*(m1[1,2] - m1[3,2]) + m1[3,1]*(m1[1,2]- m1[2,2])
[1] -1564448852668574720
如接受的答案所示,可以通過以下方法獲得並檢查正確的行列式:
#include <inttypes.h>
#include <stdio.h>
int main() {
int64_t m1[3][3] = {{INT64_C(207560540) , INT64_C(956631177) , INT64_C(1)},{ INT64_C(956631177), INT64_C(2037688522), INT64_C(1)},{INT64_C(2037688522), INT64_C(1509348670) , INT64_C(1)}};
int64_t dm1 = m1[0][0]*(m1[1][1]-m1[2][1]) - m1[1][0]*(m1[0][1] - m1[2][1]) + m1[2][0]*(m1[0][1]- m1[1][1]);
int64_t divisor = (INT64_C(1)<<31) -1;
int64_t tmp = dm1/divisor;
int64_t check = tmp * divisor;
printf("dm1 == %" PRIu64"\n",dm1);
printf("(dm1/(2^31 -1))* %" PRIu64 " == %" PRIu64 "\n", divisor, check);
}
以下文字是舊問題。 主要錯誤是使用無符號類型。
我以前的最小非工作代碼示例是:
#include <inttypes.h>
#include <stdio.h>
int main() {
uint64_t dm1 = 1564448852668573184;
uint64_t divisor = (UINT64_C(1)<<31) -1; //powl(2,31)-1;
uint64_t tmp = dm1/divisor;
uint64_t check = tmp*divisor;
printf("dm1 == %" PRIu64"\n",dm1);
printf("(dm1/(2^31 -1))* %" PRIu64 " == %" PRIu64 "\n", divisor, check);
}
它的輸出是
dm1 == 1564448852668573184
(dm1/(2^31 -1))* 2147483647 == 1564448850521091102
問題在於第二行的值應等於第一行中的值。
我怎么了 我該如何進行這項工作?
出於同樣的原因(使用整數),您將獲得10/3 10 / 3 * 3 = 9
。 剩下的部分。 10 / 3 = 3
,其余為1
。 當您乘以3
,余數會丟失,因此您得到9
而不是10
。
在這種情況下,您的余數為2147482082
,將其加到1564448850521091102
后得到1564448852668573184
。 嘗試這個:
uint64_t dm1 = 1564448852668573184;
uint64_t divisor = (UINT64_C(1)<<31) -1; //powl(2,31)-1;
uint64_t tmp = dm1/divisor;
uint64_t remainder = dm1%divisor;
uint64_t check = tmp*divisor+remainder;
並且您應該得到正確的結果。
分子不是除數的精確倍數,因此存在余數,並且商被截斷。
1564448852668573184 / 2147483647 = 728503266 remainder 2147482082
回乘
2147483647 * 728503266 + 2147482082 = 1564448852668573184
編輯:
鏈接參考中顯示的3x3矩陣的行列式為-1564448852668574749
。 這可以被2147483647
整除為-728503267
。
因此,您在某處存在算術溢出。
回答:
在鏈接的示例中,矩陣行列式的值為負。 請使用int64_t
而不是uint64_t
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.