Błąd typu

Witam,

Swoją przygodę z Rubim rozpocząłem dwie godziny temu, choć nie jest to mój pierwszy język programowania (chociaż w interpreterach niewiele dotąd siedziałem) i bardzo mnie zdziwił następujący błąd:

pierwszy.rb:18:in +': can't convert Fixnum into Array (TypeError) from pierwszy.rb:18:inFibonacci’
from pierwszy.rb:6:in `main’
from pierwszy.rb:26

w następującej metodzie:

def Fibonacci n
tmp1 =1, tmp2 =1
if n<2
return n
else
n=n-1
while n>0
wynik = tmp1 + tmp2
tmp1=tmp2
tmp2 = wynik
end
return tmp1
end
end

Oczywiście ma on miejsce przy dużych wartościach, dla małych metoda działa poprawnie. Mój zonk polega na tym, że przecież w Ruby’im jak i w Pythonie rzutowanie odbywa się niejako automatycznie, więc co niby zrobiłem źle? :slight_smile:

Pozdrawiam

Aha… nie dziwcie się, że tego Fibonacciego tak dziwnie liczę, nie chodzi o wynik tylko to czy kod działa czy nie :D.

Nie działa, poniewaz do zmiennej tmp1 przypisujesz tablice.

# dla rubiego ponizsze dwie linie sa jednoznaczne tmp1 = 1, tmp2 = 1 tmp1 = [1, tmp2 = 1]
Daje to w rezultacie tablice skladajaca sie z dwoch jedynek pod zmienna tmp1 oraz wartosc 1 pod zmienna tmp2 i stad TypeError.

Aby dzialalo, wybierz jedna z ponizszych linii:

tmp1, tmp2 = 1, 1 tmp1 = tmp2 = 1
I nie zapomnij o dekrementacji licznika petli… :wink:

Pozdrawiam

Nie zapomnij tez przeczytac: http://radarek.jogger.pl/2008/04/14/you-can-write-fortran-in-any-language/

Zacznę od poprawy błędu:
zamiast

[code=ruby]tmp1=1, tmp2=1
[/code=ruby]

spróbuj

tmp1, tmp2 = 1, 1
Twoja wersja to tak na prawdę

tmp1 = [1, b = 1]

Błąd poprawiony, ale pozwolę sobie jeszcze na kilka uwag.

Dla metod używaj małych liter (Fibonacci sugeruje nazwę klasy). Przy deklaracji raczej używa się nawiasów, zatem lepiej jest:

def fibonacci(n) #... end
Używaj lepiej dobranych nazw zmiennych, “tmp1, tmp2” niewiele mówią (myślę że w liczeniu ciągów a, b lub n1, n2 byłoby lepsze).

I jeszcze mała uwaga co do stwierdzenia:

Niestety nie jest to prawdą. Mylisz tutaj pojęcia języka typowanego statycznie/dynamicznie oraz silnie/słabo typowanego. Ruby to język dynamiczny jednak typowanie ma silne. W skrócie oznacza to, że zmienne mogą posiadać dowolne typy podczas działania programu, ale typu danego obiektu nie można zmienić). Generalnie Ruby nie próbuje na siłę dopasować typów, dlatego “5” + 5 rzuci wyjątkiem (inaczej niż php który zwróci 10).

o, super, dzięki za pomoc :slight_smile:

jeszcze jedno pytanko. Chce czytać ze standardowego wejścia dwie liczby, powiedzmy w konwencji:
scanf( “%d %d\n”, &liczbaA, &liczbaB );

korzystam z metody gets.to_i która mi niestety robi enter po każdym czytaniu. gets_chomp zamienia mi to na stringa co mi się też nie bardzo podoba więc z niej zrezygnowałem. Jak to najładniej zrobić, bo szukam w API języka i nic sensownego nie widzę :slight_smile:

Pozdrawiam

Jeśli dobrze zrozumiałem, o co chodzi, to ja bym to zrobił tak:
Dla Ruby 1.9:

liczbaA, liczbaB = gets.split(" ").map(&:to_i)

lub dla Ruby 1.8:

liczbaA, liczbaB = gets.split(" ").map{|d| d.to_i} 51345 13245 # => [51345, 13245] liczbaA # => 51345 liczbaB # => 13245