繁体   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