【问题标题】:Bernoulli-number method wrong for input > 1伯努利数法输入错误 > 1
【发布时间】:2016-05-04 12:43:37
【问题描述】:

我正在尝试实现一个返回第 n 个伯努利数的方法,如下所示:

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

即便如此,我还是不明白为什么这不能正常工作。任何帮助表示赞赏。

【问题讨论】:

    标签: smalltalk gnu-smalltalk bernoulli-numbers


    【解决方案1】:

    这里是原始算法的翻译。接收器是您的参数n,答案是从0n 的所有伯努利数的数组。

    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)
    

    编辑

    这是我在Integer 类中创建的binom: 方法

    binom: k
      | r |
      r := 1.
      1 to: k do: [:i | r := r * (self - i + 1) / i].
      ^r
    

    【讨论】:

    • 这段代码给了我一个编译错误。我正在运行 GNU Smalltalk 3.2.4。至少它告诉我伪代码是正确的,但我的实现不起作用。
    • GNU Smalltalk 不面向 Smalltalk 开发。为此,您需要具有完整工具集的 Smalltalk,尤其是可以让您修复并继续的调试器
    • @Mossmyr 你能说得更具体点吗?你得到什么编译错误?
    • @Mossmyr 请先在 Pharo 中尝试一下。在那里您将能够更好地了解哪里出了问题,这将使您更容易弄清楚如何改进 GNU-Smalltalk 的代码。
    • @Mossmyr 您可能没有使用 GNU 语法进行类扩展。如果您通过 Integer extend [ ... 而不是 Integer &gt;&gt; ... 扩展您的课程,则此答案中的代码有效
    【解决方案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)).
    

    【讨论】:

    • 我有点惊讶* 没有优先于- 并且不需要那些额外的括号。但这是真的!在 Smalltalk 中,除非括号指定,否则算术表达式是从左到右的。
    猜你喜欢
    • 1970-01-01
    • 2016-02-19
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 2020-12-17
    • 2020-04-23
    相关资源
    最近更新 更多