【问题标题】:Is it possible to do a poisson distribution with the probabilities based on integers?是否可以使用基于整数的概率进行泊松分布?
【发布时间】:2019-02-26 04:24:14
【问题描述】:

在 Solidity 和以太坊 EVM 和 Decimals 中工作不存在。有没有一种方法可以在数学上仍然使用整数创建泊松分布?它不必是完美的,即舍入或丢失一些数字是可以接受的。

【问题讨论】:

  • 泊松分布是一个计数分布,它已经基于整数了。
  • 谢谢,是的,出现次数确实如此,但概率计算都是小数。无论如何,我最终在结果中找到了我认为合理的解决方案,不确定数学是否真的正确,哈哈
  • 鉴于 a) 概率是 0 到 1 之间的数字,b) 泊松的概率涉及 exp(-lambda) 并且 e 不是有理数,因此您将得到小数。跨度>
  • 回到开头,我们是否可以用有理数来表示这种类型的分布,接受数字中的某些准确性或重要性会丢失?
  • 浮点数无论如何都有有限的精度,所以原则上你总是可以将它们表达为有理数。例如,Ruby 声称 Math::E.to_r => (6121026514868073/2251799813685248),您可以对计算的 lambda**x 部分进行类似的转换。然后,一个体面的理性库可以使用 GCD 计算来减少结果。不过,以太坊是否可以做到这一点,你自己决定。

标签: probability ethereum solidity poisson


【解决方案1】:

让我先声明以下内容不会(直接)对您的 etherium/solidity 有所帮助。但是,它会生成概率表,您可能可以将其用于您的工作。

我最终对将泊松概率表示为有理数的准确性问题很感兴趣,因此我在 Ruby 中编写了以下脚本来尝试一下:

def rational_poisson(lmbda)
  Hash.new.tap do |h|   # create a hash and pass it to this block as 'h'.
    # Make all components of the calculations rational to allow
    # cancellations to occur wherever possible when dividing
    e_to_minus_lambda = Math.exp(-lmbda).to_r
    factorial = 1r
    lmbda = lmbda.to_r
    power = 1r
    (0...).each do |x|
      unless x == 0
        power *= lmbda
        factorial *= x
      end
      value = (e_to_minus_lambda / factorial) * power
      # the following double inversion/conversion bounds the result
      # by the significant bits in the mantissa of a float
      approx = Rational(1, (1 / value).to_f)
      h[x] = approx
      break if x > lmbda && approx.numerator <= 1
    end
  end
end

if __FILE__ == $PROGRAM_NAME
  lmbda = (ARGV.shift || 2.0).to_f  # read in a lambda (defaults to 2.0)
  pmf = rational_poisson(lmbda)     # create the pmf for a Poisson with that lambda
  pmf.each { |key, value| puts "p(#{key}) = #{value} = #{value.to_f}" }
  puts "cumulative error = #{1.0 - pmf.values.inject(&:+)}"  # does it sum to 1?
end

浏览代码时要知道的事情。将.to_r 附加到一个值或表达式将其转换为有理数,即两个整数的比率;带有r 后缀的值是有理常数;而(0...).each 是一个开放式迭代器,它将循环直到满足break 条件。

那个小脚本会产生如下结果:

localhost:pjs$ ruby poisson_rational.rb 1.0
p(0) = 2251799813685248/6121026514868073 = 0.36787944117144233
p(1) = 2251799813685248/6121026514868073 = 0.36787944117144233
p(2) = 1125899906842624/6121026514868073 = 0.18393972058572117
p(3) = 281474976710656/4590769886151055 = 0.061313240195240384
p(4) = 70368744177664/4590769886151055 = 0.015328310048810096
p(5) = 17592186044416/5738462357688819 = 0.003065662009762019
p(6) = 1099511627776/2151923384133307 = 0.0005109436682936699
p(7) = 274877906944/3765865922233287 = 7.299195261338141e-05
p(8) = 34359738368/3765865922233287 = 9.123994076672677e-06
p(9) = 67108864/66196861914257 = 1.0137771196302974e-06
p(10) = 33554432/330984309571285 = 1.0137771196302975e-07
p(11) = 33554432/3640827405284135 = 9.216155633002704e-09
p(12) = 4194304/5461241107926203 = 7.68012969416892e-10
p(13) = 524288/8874516800380079 = 5.907792072437631e-11
p(14) = 32768/7765202200332569 = 4.2198514803125934e-12
p(15) = 256/909984632851473 = 2.8132343202083955e-13
p(16) = 16/909984632851473 = 1.7582714501302472e-14
p(17) = 1/966858672404690 = 1.0342773236060278e-15
cumulative error = 0.0

【讨论】:

  • 非常好的代码,感谢您的分享。 .to_r 很有趣,我特别注意到 approx = Rational(1, (1 / value).to_f) 。有很多东西需要消化和试验,使用像 Solidity 这样有限的语言工作是一个有趣和令人沮丧的挑战,你可以随时在 remix.ethereum.org Solidity IDE 尝试它,当我更进一步时,我会回来分享一个链接,再次感谢@pjs
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
相关资源
最近更新 更多