From: labocho@... Date: 2016-12-08T02:22:03+00:00 Subject: [ruby-core:78535] [Ruby trunk Feature#12871] Using the algorithm like math.fsum of Python for Array#sum Issue #12871 has been updated by Keisuke NISHI. Thank you. Julia's algorithm looks good. But in some case, Python's algorithm is still better than that. ~~~ # julia 0.5.0 sum_kbn([1.0e100, 1.0, 1.0e-100, -1.0, -1.0e100]) # => 0.0 ~~~ ~~~ python # python 3.5.2 from math import fsum fsum([1.0e100, 1.0, 1.0e-100, -1.0, -1.0e100]) # => 1e-100 ``` Is it acceptable? ---------------------------------------- Feature #12871: Using the algorithm like math.fsum of Python for Array#sum https://bugs.ruby-lang.org/issues/12871#change-61919 * Author: Keisuke NISHI * Status: Closed * Priority: Normal * Assignee: Kenta Murata ---------------------------------------- Array#sum uses the Kahan's algorithm for Float values now. But it returns inaccurate value in some case like below. ~~~ ruby # ruby 2.4.0-preview2 [10000000000.0, 0.0000000001, -10000000000.0].sum #=> 0.0 (expected 0.0000000001) ~~~ Python's math.fsum uses another algorithm. It saves all digits, and returns accurate value in such a case. (See: https://github.com/python/cpython/blob/d267006f18592165ed97e0a9c2494d3bce25fc2b/Modules/mathmodule.c#L1087) ~~~ python # python 3.5.2 from math import fsum fsum([10000000000.0, 0.0000000001, -10000000000.0]) #=> 0.0000000001 ~~~ I propose to use the algorithm like math.fsum of Python for Array#sum. This is an example implementation in Ruby. ~~~ ruby class Array # This implementation does not consider non float values def sum partials = [] each do |x| i = 0 partials.each do |y| x, y = y, x if x.abs < y.abs hi = x + y # upper bits lo = y - (hi - x) # lower bits (lost) if lo != 0.0 partials[i] = lo i += 1 end x = hi end partials[i..-1] = [x] end partials.inject(0.0, :+) end end ~~~ -- https://bugs.ruby-lang.org/ Unsubscribe: