Я пытаюсь реализовать метод, который возвращает число бернулли n: th, например:
Object subclass: #Bernoulli.
Bernoulli class extend [
"******************************************************
* Psuedo code for bernoulli method I'm working from:
*
* function B(n)
* B[1] <-- 1
* for m <-- 2 to n+1 do
* B[m] <-- 0
* for k <-- 1 to m - 1 do
* B[m] <-- B[m] − BINOM (m, k-1) * B[k]
* B[m] <-- B[m]/m
* return B[n+1]
*
* function BINOM (n, k)
* r <-- 1
* for i <-- 1 to k do
* r <-- r · (n − i + 1)/i
* return r
******************************************************"
bernoulli: n [
"Initialize variables"
| B size innerLoop temp|
size := n + 1.
B := Array new: size.
B at: 1 put: 1. "B[1] <-- 1"
2 to: size do: [:m | "for m <-- 2 to (n+1) do"
B at: m put: 0. "B[m] <-- 0"
innerLoop := m - 1.
1 to: innerLoop do: [:k | "for k <-- 1 to (m-1) do"
B at: m put: (B at: m) - (Bernoulli binom: m k: (k-1)) * (B at: k). "B[m] <-- B[m] − BINOM(m, k-1) * B[k]"
].
B at: m put: (B at: m) / m. "B[m] <-- B[m] / m"
].
^(B at: size) "return B[n+1]"
]
binom: n k:k [
| r i |
r := 1. "r <-- 1"
1 to: k do: [:i | "for i <-- 1 to k do"
r := r * (n - i + 1) / i. "r <-- r * (n - i + 1)/i"
].
^r "return r"
]
]
z := Bernoulli bernoulli: 3.
z printNl.
(Я постарался прокомментировать код).
Однако для входов n> 1 я получаю неправильное число Бернулли:
- n = 0 -> 1 (правильно).
- n = 1 -> -1/2 (правильно)
- n = 2 -> 2/3 (должно быть 1/6)
- n = 3 -> -7/12 (должно быть 0)
- n = 4 -> 77/45 (должно быть -1/30)
- n = 5 -> 3157/9720 (должно быть 0)
Я предполагаю, что я как-то неправильно реализовал внутренний цикл или внутренний-внутренний цикл, поскольку ввод n <2 работает правильно (а n <2 полностью пропускает внутренний-внутренний цикл). Псевдо-код, с которым я работаю, также может быть неправильным, но я сомневаюсь в этом, поскольку только вчера я заставил его работать в COBOL. Метод бинома работает правильно, сам тестировал.
Тем не менее, я не могу понять, почему это не работает должным образом. Любая помощь приветствуется.
2 ответа
Вы (я) опускаете скобки вокруг предложения (Bernoulli binom: m k: (k-1)) * (B at: k)
. Должно получиться так:
B at: m put: (B at: m) - ((Bernoulli binom: m k: (k-1)) * (B at: k)).
Вот перевод оригинального алгоритма. Получатель - это ваш параметр n
, а ответ - массив всех чисел Бернулли от 0
до n
.
Integer >> bernoulliNumbers
| bernoulli |
bernoulli := Array new: self + 1.
bernoulli at: 1 put: 1.
2 to: self + 1 do: [:m |
bernoulli at: m put: 0.
1 to: m - 1 do: [:k |
bernoulli
at: m
put: (bernoulli at: m) - ((m binom: k - 1) * (bernoulli at: k))].
bernoulli at: m put: (bernoulli at: m) / m].
^bernoulli
Пример:
5 bernoulliNumbers -> #(1 -1/2 1/6 0 -1/30 0)
ИЗМЕНИТЬ
Вот метод binom:
, который я создал в классе Integer
binom: k
| r |
r := 1.
1 to: k do: [:i | r := r * (self - i + 1) / i].
^r
Похожие вопросы
Новые вопросы
smalltalk
Smalltalk - один из старейших объектно-ориентированных языков программирования. Это начало многих аспектов, которые современные разработчики принимают как должное: Виртуальные машины (Smalltalk - это интерпретируемый язык) Иды Чистый объектный подход (без примитивов или ключевых слов вообще) Закрытия (называемые блоками) Изображение (то есть не основанный на файлах язык) Расширенные методы отладки (остановка программ на лету, проверка, написание или изменение кода на лету)