这是我的代码:
0
打印
1.37847e+11
这是错误的答案,但如果我将整数类型更改为double将打印<%= form_for @changeset, image_path(@conn, :create),
[multipart: true], fn f -> %>
这是正确的答案,我的问题是为什么使用int64_t给我错误的答案
答案 0 :(得分:9)
和int64_t不会溢出
但确实如此。为了调试这样的事情,你可以在GCC或clang中使用-fsanitize=signed-integer-overflow
(隐含-fsanitize=undefined
)来运行,看看:
运行时错误:有符号整数溢出:21 * 2432902008176640000无法在类型&#39; long&#39;中表示 运行时错误:有符号整数溢出:2432902008176640000 * 2432902008176640000无法用类型&#39; long&#39;
表示
答案 1 :(得分:5)
40!
约为8e47
。 64位有符号整数最多可以保持2^63-1
,大约1e19
。
factorial(40)
确实溢出,并且由于有符号整数类型的溢出是未定义的行为,因此无法解释您观察到的任何内容。
答案 2 :(得分:5)
欢迎来到有限精度数字的世界!事实(40)是815915283247897734345611269596115894272000000000或0x8eeae81b84c7f27e080fde64ff05254000000000,即使在uint64_t
中也不适合128位long long
,因为它实际上需要160位!
但二项式系数40,20确实可以使用uint64_t
计算,只要你使用人类在计算机到处前所使用的正确算法:
integer binomial_coefficient(integer n, integer r) {
integer bc = 1;
integer q = n - r;
for(integer i=1; i<=r; i++) {
br = br * (q + i) / i;
}
return bc;
}
这个将为您提供正确的值137846528820,没有溢出。
(上面的函数省略了r&lt; = n / 2的测试,可以进行额外的优化,因为Cn,p是构造Cn,n-p)