计算行列式并使用 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 * 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
.
这个问题已经过编辑以澄清它。
我有以下矩阵,在 [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 * 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
.