簡體   English   中英

計算行列式並使用uint64_t C類型的除法和乘法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM