Julia 中 2 个正数的相乘得到负积

Multiplication of 2 positive numbers in Julia gives a negative product

提问人:René 提问时间:5/1/2022 最后编辑:René 更新时间:5/2/2022 访问量:190

问:

在 Julia 1.7.2 中,乘以并返回负积。我期望的产品是.30370006913037000693-92233708705010727539223373203208478863

function m(a::BigInt, b::BigInt)::BigInt
    a * b
end

此函数给出相同的否定结果。

关于如何在 Julia 1.7.2 中获得正确答案的任何想法?3037000691 * 3037000693

P.S.
我确实遇到了这个问题,在对(大)孪生素数进行一些数学运算时。

整数 朱莉娅 乘法 biginteger int128

评论


答:

6赞 Sash Sinha 5/1/2022 #1

尝试像这样调用函数:

julia> m(BigInt(3037000691), BigInt(3037000693))
9223373203208478863

或将您的功能更改为以下任一功能:

# TL;DR: Use this it is the fastest.
function m1(a::Int64, b::Int64)::Int128
    Int128(a) * Int128(b)
end

function m2(a, b)::BigInt
    BigInt(a) * BigInt(b)
end

function m3(a::Int64, b::Int64)::BigInt
    BigInt(a) * BigInt(b)
end

请注意,从技术上讲,您只需要强制转换 ab,但我认为这会降低可读性。

用法示例:

julia> m1(3037000691, 3037000693)
9223373203208478863
julia> m2(3037000691, 3037000693)
9223373203208478863
julia> m3(3037000691, 3037000693)
9223373203208478863

在这种情况下,您应该使用 ,它仅使用 s,因为不可能将两个值相乘以溢出 :m1Int128Int64Int128

julia> m1(9223372036854775807, 9223372036854775807) # Max val for Int64 squared.
85070591730234615847396907784232501249

通常,尽可能不使用 's 并明确说明函数中的类型将显著提高性能:BigInt

julia> using BenchmarkTools

julia> @benchmark m1(3037000691, 3037000693)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max):  0.049 ns … 7.780 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     0.060 ns             ┊ GC (median):    0.00%
 Time  (mean ± σ):   0.064 ns ± 0.078 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

   ▁          █         ▃▆▃         ▂                       ▁
  ▆█▆▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁███▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▄▆▄▁▁▁▁▁▁▁▁▁█ █
  0.049 ns    Histogram: log(frequency) by time      0.1 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark m2(3037000691, 3037000693)
BenchmarkTools.Trial: 10000 samples with 199 evaluations.
 Range (min … max):  413.317 ns …  2.404 ms  ┊ GC (min … max):  0.00% … 64.79%
 Time  (median):     507.080 ns              ┊ GC (median):     0.00%
 Time  (mean ± σ):     1.957 μs ± 42.299 μs  ┊ GC (mean ± σ):  26.95% ±  1.29%

  ▇▆█▇▆▅▅▄▄▃▂▂▁▂▁                                              ▂
  █████████████████▇█▇▆▆▆▅▆▄▄▆▄▅▅▁▄▄▅▄▄▁▃▄▄▄▄▃▃▁▄▁▄▃▃▄▄▁▃▄▁▄▄▄ █
  413 ns        Histogram: log(frequency) by time      2.39 μs <

 Memory estimate: 128 bytes, allocs estimate: 7.

julia> @benchmark m3(3037000691, 3037000693)
BenchmarkTools.Trial: 10000 samples with 199 evaluations.
 Range (min … max):  414.774 ns …  2.487 ms  ┊ GC (min … max):  0.00% … 64.53%
 Time  (median):     496.080 ns              ┊ GC (median):     0.00%
 Time  (mean ± σ):     1.895 μs ± 41.026 μs  ┊ GC (mean ± σ):  24.60% ±  1.20%

  ▄ ▂▁ ▂█▄                                                      
  █▄██▇████▇▇▇▄▃▃▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▁▂▂ ▃
  415 ns          Histogram: frequency by time         1.14 μs <

 Memory estimate: 128 bytes, allocs estimate: 7.

评论

0赞 René 5/1/2022
谢谢你的回答。我应该如何(重新)编写函数以返回正确答案?我想使用参数 037000691 和 3037000693 而不是 big(037000691) 和 big(3037000693)。
1赞 Sash Sinha 5/1/2022
这对你有用吗?
0赞 Antonello 5/2/2022
出于好奇,在用于数字插补的主要高级语言(例如R,Python,Matlab..)中,是否有任何语言可以自动执行大小写而不是溢出?
0赞 lungben 5/2/2022
Python 默认的整数类型对应于 Julia 的 BigInt,即 overflow-save,但速度非常慢。相比之下,Numpy 使用溢出的整数,类似于 Julia。
4赞 Przemyslaw Szufel 5/2/2022 #2

应该注意的是,问题中定义的函数不会提供负面结果(考虑到函数的语法,这将是非常错误的)。m

julia> m(3037000691, 3037000693)
ERROR: MethodError: no method matching m(::Int64, ::Int64)
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

Julia 不执行自动转换 from to 。总而言之,这意味着您已经(或刚刚)定义了它,并且为您的参数值调用了它。Int64BigIntm(::Int64, ::Int64)m(::Any, ::Any)

[该怎么办在另一个公认的答案中描述]