💭

[Feature #21527] Math.log1p と Math.expm1 を追加する提案

に公開
2025/08/30

[Feature #21527] Proposal: Math.log1p and Math.expm1

  • Math.log1p と Math.expm1 を追加する提案
  • それぞれ以下と同じ挙動になる
    • Math.log1p(x) -> Math.log(x + 1)
    • Math.expm1(x) -> Math.exp(x) - 1
  • 直接右のコードを呼び出したときと比較して専用のメソッドを用意することで以下のような誤差をなくすことができるみたいですね
# log / exp を呼び出すと精度が失われる
p Math.log(1 + 1.0e-16) #=> 0.0
p Math.exp(1.0e-16) - 1 #=> 0.0

# log1p / expm1 は精度を失わずに計算できる
p Math.log1p(1.0e-16)   #=> 1.0e-16
p Math.expm1(1.0e-16)   #=> 1.0e-16
  • これらのメソッドはいずれも他の言語でも標準で用意されている一般的な関数みたいですね
    • C99 にも標準で定義されている関数になる
  • log1p / expm1 という名前がわかりづらい、というコメントも書かれてしますがこれらの名前も割と一般的な名前みたい
  • 他には fiddle を経由して直接関数を呼び出すようにする案とかもコメントされていますね
require 'fiddle'
log1p = Fiddle::Function.new(Fiddle.dlopen(nil)["log1p"], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)
p log1p.call(1.0e-16) # => 1.0e-16
  • この提案は承認されて開発版の Ruby 3.5-dev では既に実装済み
# Ruby 3.5 から利用可能
p Math.log1p(1.0e-16)   #=> 1.0e-16
p Math.expm1(1.0e-16)   #=> 1.0e-16
GitHubで編集を提案

Discussion