Проблема: создать функцию с одним входом. Вернуть индекс массива, содержащего последовательность Фибоначчи (начиная с 0), элемент которой соответствует входному значению функции.
16 ~ │ def fib(n)
17 ~ │ return 0 if n == 0
18 │
19 ~ │ last = 0u128
20 ~ │ current = 1u128
21 │
22 ~ │ (n - 1).times do
23 ~ │ last, current = current, last + current
24 │ end
25 + │
26 + │ current
27 │ end
28 │
60 │ def usage
61 │ progname = String.new(ARGV_UNSAFE.value)
62 │
63 │ STDERR.puts <<-H
64 │ #{progname} <integer>
65 │ Given Fibonacci; determine which fib value would
66 │ exist at <integer> index.
67 │ H
68 │
69 │ exit 1
70 │ end
71 │
72 │ if ARGV.empty?
73 │ usage
74 │ end
75 │
76 │ begin
77 ~ │ i = ARGV[0].to_i
78 ~ │ puts fib i
79 │ rescue e
80 │ STDERR.puts e
81 │ usage
82 │ end
Мое решение проблемы ни в коем случае не изящно, и я сделал это в 2 часа ночи, когда Я был довольно уставшим. Поэтому я не ищу более элегантное решение. Что меня интересует, так это то, что если я запускаю результирующее приложение с входным значением больше 45, то я получаю Arithmetic overflow
. Я думаю, что сделал что-то не так с набором переменных Я запустил это в Ruby, и он работает нормально, поэтому я знаю, что это не проблема с оборудованием ...
Может ли кто-нибудь помочь мне найти, что я сделал не так в этом? Я тоже все еще копаю. Я только начал работать с Кристаллом на этой неделе. Это мое второе приложение / эксперимент с ним. Мне действительно нравится, но я еще не знаю о некоторых его особенностях.
РЕДАКТИРОВАТЬ
Обновленный скрипт, чтобы отразить предлагаемое изменение и результат времени выполнения от указанного изменения. С этим изменением я могу теперь успешно запустить программу с номером 45, но только до 90-х. Это интересно. Я собираюсь пройти через это и посмотреть, где мне может понадобиться добавить дополнительное явное приведение. Кажется, очень не интуитивно понятно, что изменение типа во время инициации не «зависало» на протяжении всего времени выполнения, которое я попробовал первым, и это не удалось. Что-то здесь не имеет смысла для меня.
Исходные результаты
$ crystal build fib.cr
$ ./fib 45
1836311903
$ ./fib 46
Arithmetic overflow
$ ./fib.rb 460
985864329041134079854737521712801814394706432953315\
510410398508752777354792040897021902752675861
Последние результаты
$ ./fib 92
12200160415121876738
$ ./fib 93
Arithmetic overflow
./fib <integer>
Given Fibonacci; determine which fib value would
exist at <integer> index.
Edit ^ 2
Теперь также решили, что, возможно, ARGV[0]
является проблемой. Поэтому я изменил вызов на f()
на:
62 begin
63 i = ARGV[0].to_u64.as(UInt64)
64 puts f i
65 rescue e
66 STDERR.puts e
67 usage
68 end
и добавил отладочную печать, чтобы показать типы используемых переменных:
22 return 0 if p == 0
23
24 puts "p: %s\tfib_now: %s\tfib_last: %s\tfib_hold: %s\ti: %s" % [typeof(p), typeof(fib_now), typeof(fib_last), typeof(fib_hold), typeof(i)]
25 loop do
p: UInt64 fib_now: UInt64 fib_last: UInt64 fib_hold: UInt64 i: UInt64
Arithmetic overflow
./fib <integer>
Given Fibonacci; determine which fib value would
exist at <integer> index.
Редактировать ^ 3
Обновлен с последним кодом после исправления ошибки Jonne. Оказывается, проблема в том, что я пересекаю границы структуры даже с 128-битными целыми числами без знака. Ruby обрабатывает это изящно. Похоже, что в хрустале я должен изящно справиться с этим.