我在对大数字进行除法时遇到问题。我有一个while循环,如果索引在数组限制内,并且余数为零,它会对数字进行除法运算:
while ((i + j*arr[i]) <= lim && arr[i + j*arr[i]] % arr[i] == 0)
arr[i + j*arr[i]] /= arr[i]
end
Im在arr[i]<(150*10^6)^2
的最大值上使用Int64的数组,即使更改为Int128也无济于事,BigInt是不可能的,因为它花费了太多时间。我不明白为什么只有当余数为零时,循环才会出现Inexact错误。和typemax(Int64)>max(arr)
这是完整的错误:
InexactError: Int64(1.8014400929875968e15)
in top-level scope at P-146-Investigating a Prime Pattern:51
in test at P-146-Investigating a Prime Pattern:39
in setindex! at basearray.jl:826
in convert at basenumber.jl:7
in Int64 at basefloat.jl:710
它似乎只有在数组中的值高于(90*10^6)^2
之后才会发生
TLDR:使用÷
。
使用Julia中的/
函数对整数进行除法运算会返回浮点数。重要的是,它在执行除法之前将整数提升为浮点数。例如,数字10^16-1
显然可以被三整除:
julia> 9999999999999999 % 3
0
然而,如果我们尝试用/
进行这种划分,我们不会得到正确的答案:
julia> 9999999999999999 / 3
3.3333333333333335e15
julia> using Printf
julia> @printf "%f" 9999999999999999 / 3
3333333333333333.500000
所以,当然,试图将上面的数字存储在一个整数数组中会抛出一个不精确的错误。但为什么会这样呢?你已经超过maxintfloat(Float64)
了。由于浮点数字的精度约为15位小数,超过该值后,它们将无法准确表示每一个整数。他们开始跳过(并绕过!(他们。因此,你并不是真的把10^16-1
除以三,而是把10^16除以三!
julia> 10^16-1
9999999999999999
julia> Float64(10^16-1)
1.0e16
使用÷
(也就是div
(要好得多——它不仅可以处理这些情况而不必担心浮点精度,而且还可以保持整数形式:
julia> 9999999999999999 ÷ 3
3333333333333333
问题是/
操作产生float
,因此下面的=
尝试将浮点值分配给Int
类型的数组元素。考虑这个例子
> a = [11]
> b = [2]
> a[1] /= b[1]
ERROR: InexactError: Int64(5.5)
Stacktrace:
[1] Int64 at ./float.jl:710 [inlined]
[2] convert at ./number.jl:7 [inlined]
[3] setindex!(::Array{Int64,1}, ::Float64, ::Int64) at ./array.jl:849
[4] top-level scope at REPL[6]:1
因此,它试图将CCD_ 16分配给由CCD_ 17组成的数组的元素。
根据您的任务,您可以执行以下操作之一
- 以某种方式将数组声明为浮点数组
> a = [11.0]
1-element Array{Float64,1}:
11.0
> b = [2.0]
> a[1] /= b[1]
5.5
- 使用整数除法(
div
或等效的÷
(进行除法
> a = [11]
> b = [2]
> a[1] ÷= b[1]
5
至于你最初的问题,为什么会产生这个错误,我认为,由于你有相当大的数字,在转换为float和下面的除法后,你会得到一个不精确的结果,无法转换回Int
。
使用整数除法÷
/div
有时会有风险——您可能会因为舍入而丢失值,甚至没有注意到。因此,在许多情况下,可以考虑使用Julia对有理数的支持。
julia> u = 9999999999999999 // 3
3333333333333333//1
julia> u % 3 == 0
true
由于有理数的存储方式,您可以期待良好的性能(尽管不如整数除法(:
julia> dump(u)
Rational{Int64}
num: Int64 3333333333333333
den: Int64 1