2015-03-05 3 views
0

Я пытаюсь сделать программу для вычисления длины последовательности Collatz для всех чисел от 1 до 100. В принципе, если у меня есть нечетное число, я должен умножить ее на 3 и добавьте 1 (n * 3 + 1), и если у меня есть четное число, мне нужно разделить его на 2 (n/2), а затем продолжать делать это до тех пор, пока он не достигнет 1 и в конце распечатает счетчик раз число было либо делится на 2 или на 3 multiplyed и добавил 1. Вот что я до сих пор:OCaml, последовательность Collatz, не удается распечатать результат

let stevec = ref 0; 
let n = ref 1; 
for i = 1 to 100 do 
    n := i; 
    while !n != 1 do 
     if (n mod 2 = 0) then 
      stevec := !stevec + 1; 
      n := !n/2; 
     if (n mod 2 = 1) then 
      stevec := !stevec + 1; 
      n := 3 * !n + 1; 
    done 
    print_int (stevec); 
done;; 

После я запускаю код, который я получаю ошибку синтаксиса и print_int получить подчеркнут, так что я думаю, есть проблема с этим, но я даже не уверен в этом.

+0

Я могу исправить ошибки синтаксиса, но когда я запустил код, он не завершился, поэтому я думаю, что в коде есть логические проблемы. –

+0

Вы пытались использовать функциональное программирование вместо побочных эффектов? Если вы это сделаете, ваш код OCaml будет более читабельным и доступным для записи. – PatJ

+0

Я просто изучаю Ocaml, но я уверен, что на языке, таком как java или python, эта логика должна работать ... – minus

ответ

3

Существует несколько проблем с вашим кодом, поэтому давайте рассмотрим его.

let stevec = ref 0; 
let n = ref 1; 

Вы не должны написать такой код, как и ; является выражением сепаратором (и вы используете его здесь в качестве разделителя декларации).

Правильный подход зависит от того, хотите ли вы, чтобы ваше заявление было локальным или полным.

(* local declaration *) 
let stevec = ref 0 in 
let n = ref 1 in 

(* toplevel declaration *) 
let stevec = ref 0;; 
let n = ref 1;; 

Затем вы набрали while !n != 1 do. Это не должно использоваться, поскольку вы выполняете физическое неравенство между целыми числами, тогда как вам требуется структурное равенство. Ну, это тоже будет работать из-за поведения OCaml по целым числам, но для хорошей практики вам нужно использовать <> вместо !=.

Теперь давайте посмотрим на теле вашего цикла в:

if (!n mod 2 = 0) then 
    stevec := !stevec + 1; 
    n := !n/2; 
if (!n mod 2 = 1) then 
    stevec := !stevec + 1; 
    n := 3 * !n + 1; 

Обратите внимание на отсутствии какой-либо fi или закрывающей скобки? Это потому, что в OCaml выполняется только следующее выражение после then. И приоритет над ; не идет так, как вы этого хотите. Вы можете использовать parens или более явную конструкцию begin ... end. Чтобы доказать, что работает begin ... end, я заменил ваш второй тест на инструкцию else.

if (!n mod 2 = 0) then 
    begin 
    stevec := !stevec + 1; 
    n := !n/2; 
    end 
else 
    begin 
    stevec := !stevec + 1; 
    n := 3 * !n + 1; 
    end 

Наконец while ... done быть собой выражение, вы должны поставить ; в конце.

И вот как вы удаляете ошибки из своего кода.
...

Это явно не «правильный путь» для этого в OCaml. Главным преимуществом FP ​​является его близость к математике, и вы здесь пытаетесь определить математическую функцию. Итак, давайте сделаем это функциональным способом:

let is_even x = (x mod 2) = 0;; 
let rec collatz counter n = 
    if n = 1 
    then counter 
    else collatz (counter+1) (if is_even n then n/2 else 3*n+1);; 
let() = 
for i = 1 to 100 do 
    print_int (collatz 0 i); 
    print_newline(); 
done;; 

Не выглядит ли это лучше? Не стесняйтесь просить о каких-либо разъяснениях, конечно.

+0

Большое спасибо за то, что нашли время, чтобы объяснить. У меня есть вопрос (пусть rec collatz counter n =).как работает этот collatz counter в середине (пусть rec n), что он делает точно. Я просто не знаком с этим типом кодирования. – minus

+0

В принципе, эта строка объявляет (это 'let') рекурсивную (' rec') функцию с именем 'collatz', которая принимает два аргумента' counter' и 'n'. Рекурсивная реализация позволяет 'collatz' вызывать себя, что позволяет ему зацикливаться (это то, как петли реализуются в функциональном программировании). – PatJ

+0

Вы должны взглянуть на «основы OCaml» ocaml.org: http://ocaml.org/learn/tutorials/basics.html – PatJ

Смежные вопросы