From: tomoyapenguin@... Date: 2017-01-08T15:42:23+00:00 Subject: [ruby-core:79014] [Ruby trunk Bug#13116] modulo, divmod range problem: float_val % 1 may return 1.0 Issue #13116 has been reported by tomoya ishida. ---------------------------------------- Bug #13116: modulo, divmod range problem: float_val % 1 may return 1.0 https://bugs.ruby-lang.org/issues/13116 * Author: tomoya ishida * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16] * Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN ---------------------------------------- mod, divmod range problem: float_val % 1 may return 1.0 x % y sometimes returns y (not in 0 <= result < y) ```ruby float_val = 0.0.prev_float float_val % 1 #=> 1.0 Math.sin(2*Math::PI) % 10 #=> 10.0 ``` I not sure this is a bug or a feature but I think returning x.prev_float rather than x would be appropriate. ```ruby # when would this feature cause problem?: require 'chunky_png' image = ChunkyPNG::Image.new 100, 100 points = 100.times.map{|i|[10*Math.sin(Math::PI*i/10), i, 0xaabbccff]} # render points to an image object(circular boundary) points.each do |x, y, color| image[(x % image.width).floor, (y % image.height).floor] = color # => ChunkyPNG::OutOfBounds: Coordinates (100,20) out of bounds! end image.save 'out.png' # to avoid error: (x % w % w).floor [(x % w).floor, w - 1].min xx = (x % w).floor; xx -= 1 if xx == w # but it's a little bit weird ``` ```ruby # sample implementation in ruby: class Float alias_method :original_modulo, :% alias_method :original_divmod, :divmod def divmod x div, mod = original_divmod x if mod == x mod = x > 0 ? mod.prev_float : mod.next_float end [div, mod] end def % x mod = original_modulo x return mod if mod != x x > 0 ? mod.prev_float : mod.next_float end end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: