斐波那契问题导致算术溢出

问题描述 投票:1回答:1

问题:用一个输入创建一个函数。返回包含斐波那契序列(从0开始)的数组的索引,该数组的元素与函数的输入匹配。

16   │ def f(p)
17   │   fib_now   = 0u64
18   │   fib_last  = 0u64
19   │   fib_hold  = 0u64
20   │   i         = 0u64
21   │ 
22   │   return 0 if p == 0
23   │ 
24   │   loop do
25   │     if fib_now == 0
26   │       fib_last = 0
27   │       fib_now  = 1
28   │       i += 1
29   │       next
30   │     end
31   │ 
32   │     fib_hold = fib_now
33   │ 
34   │     fib_now  = fib_last + fib_now
35   │     fib_last = fib_hold
36   │ 
37   │     #puts "fib_last is: %s\tfib_now is: %s" % [fib_last, fib_now]
38   │ 
39   │     return fib_now if i == p
40   │ 
41   │     i += 1
42   │   end
43   │ end
44   │ 
45   │ def usage
46   │   progname = String.new(ARGV_UNSAFE.value)
47   │ 
48   │   STDERR.puts <<-H
49   │   #{progname} <integer>
50   │     Given Fibonacci; determine which fib value would
51   │     exist at <integer> index.
52   │   H
53   │ 
54   │   exit 1
55   │ end
56   │ 
57   │ if ARGV.empty?
58   │   usage
59   │ end
60   │ 
61   │ begin
62   │   puts f ARGV[0].to_i64 # maybe this is problematic?
63   │ rescue e
64   │   STDERR.puts e
65   │   usage
66   │ end

$ crystal build fib.cr
$ ./fib 45
1836311903
$ ./fib 46
Arithmetic overflow
$ ./fib.rb 460
985864329041134079854737521712801814394706432953315\
510410398508752777354792040897021902752675861

我对这个问题的解决方案绝非优雅,我在很累的时候是在凌晨2点做到的。所以我不是在寻找一个更优雅的解决方案。我很好奇的是,如果我使用大于45的输入来运行结果应用程序,那么系统将显示Arithmetic overflow。我认为我的变量输入方式做错了。我在Ruby中运行了它,它运行得很好,所以我知道这不是硬件问题...

有人可以帮我找到我做错了什么吗?我也在挖掘。我本周刚开始与Crystal合作。这是我的第二次应用/实验。我真的很喜欢,但是我还不知道它的某些特质。

crystal-lang
1个回答
3
投票

Crystal中的默认整数类型为Int32,因此,如果不显式指定整数文字的类型,则可以得到。

特别是行

fib_last = 0
fib_now  = 1

将变量转换为有效类型Int32。要解决此问题,请确保指定这些整数的类型,因为您不需要负数,UInt64在这里似乎最合适:

fib_last = 0u64
fib_now  = 1u64

还要注意我在这里使用的文字语法。您的0.to_i64创建一个In32,然后再创建一个Int64。编译器将足够聪明,可以在发行版本的编译时进行此转换,但是我认为只使用文字语法会更好。

© www.soinside.com 2019 - 2024. All rights reserved.