Smalltalk Фибоначчи

Я должен использовать Smalltalk, чтобы вернуть n-е число Фибоначчи, я раньше не использовал этот язык. Эта программа возвращает 1 для любого ввода, и я не знаю почему. Я даже не повторял цикл for. Может ли кто-нибудь помочь мне? Благодарю.

'Which fibonacci number do you want? (n>2)' printNl.
n := stdin nextLine asInteger.

(n <= 2)
    ifTrue: ['Type a larger number, F(1) and F(2) equals 1!' displayNl.]
    ifFalse: [  
        result:= 1.
        parent := 1.
        gparent := 1.   
        2 to: n do: [ :i | [
                result := (parent + gparent).
                gparent := parent.
                parent := result.
                'come on, do something' displayNl.
            ]
        ].
        result displayNl.
    ].

5 ответов

Решение

У вас есть дополнительный набор скобок в теле цикла, что позволяет создавать (но не выполнять) блок на каждой итерации цикла. Вот что вы хотели написать:

    2 to: n do: [ :i |
        result := (parent + gparent).
        gparent := parent.
        parent := result.
        'come on, do something' displayNl.
    ].

Вы можете упростить это еще больше, если хотите:

a := b := 1.
(n - 1) timesRepeat: [a := b + (b := a)].

Полусимметричное "храповое" выражение внутри блока - одно из моих любимых писем в Smalltalk. Не обязательно выигрывать конкурсы по читабельности, но я думаю, что это круто. Это приводит к строгому соблюдению правил Smalltalk слева направо, в то время как в других языках мы хотели бы мысленно оценить самое правое назначение, прежде чем помещать (оригинальное) значение b в положении приемника.

Обратите внимание, как я заменил ваш 2 to: n do: выражение, так как вы не используете i переменная аргумента.

Почему бы вам не определить метод

fib
  ^ self < 2
    ifTrue: [ 1 ]
    ifFalse: [ (self - 2) fib + (self - 1) fib ]

в классе Integer и использовать его для расчета последовательности?

  1. Smalltalk не является процедурным языком, вы не должны писать только длинный скрипт в одном методе.
  2. Используйте красоту рекурсии
fib := [:n |
        (n<=1)
            ifTrue: [n]
            ifFalse:
                [
                    (fib value: (n-1)) +
                    (fib value: (n-2))
                ]
    ].
fib value 10

для VisualWorks

(1 to: n)
inject: OrderedCollection new
into: [ :coll :each |
    | p pp n |
    p := coll at: (each - 1) ifAbsent: [ 0 ].
    pp := coll at: (each - 2) ifAbsent: [ 0 ].
    n := p + pp.
    ((n = 0) and: [ each = 1 ])
        ifTrue: [ n := 1 ].
    coll 
        add: n;
        yourself ].

В фаро.

Другие вопросы по тегам