Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Match Math.sqrt to default behaviour with Integers #43

Open
wants to merge 1 commit into from

3 participants

@ozzyaaron

I realise that the mathn library changes this, but I think most developers rely on Math.sqrt returning a float like the default math.rb library. As such when we use ruby-unit + other gems that rely on Math.sqrt returning a Float we can get issues (alchemist, or rgeo for example).

Aaron Todd Match Math.sqrt to default behaviour with Integers
I realise that the mathn library changes this, but I think most developers rely on Math.sqrt returning a float like the default math.rb library. As such when we use ruby-unit + other gems that rely on Math.sqrt returning a Float we can get issues (alchemist, or rgeo for example).
ca34f40
@olbrich
Owner

Unit math is done using rationals as much as possible to avoid problems with round off errors. It also uses mathn internally. To my knowledge, the behavior you are seeking to enforce is not documented nor guaranteed to be the case for the standard Math.sqrt function.

Can you provide me with a more detailed example of how this causes problems?

@ozzyaaron
@jasonhutchens

I think we can agree that mathn (which is a Ruby core library) can cause bugs in 3rd-party gems that may make assumptions about Math (such as the assumption in RGeo that you should be able to call nan? on the result of Math.sqrt, which breaks when it starts returning Integers).

Another problem with mathn is that it's not very performant. For example:

#!/usr/bin/env ruby

def test_performance
  require 'benchmark'
  puts Benchmark.realtime { 1_000_000.times { 1 / Math.sqrt(2) } }
end

test_performance

require 'ruby-units'

test_performance

On my machine, this prints:

1.55383014678955
15.2412781715393

That is, using ruby-units has caused my benchmark to take almost 10 times as long to run. And the benchmark isn't even doing any unit calculations at all!

I believe a fundamental criteria of good library design is that there shouldn't be any side-effects of this kind. Using ruby-units shouldn't cause other gems to break. And I believe that the choice of greater numerical accuracy should be in the hands of the user of the gem (that is, we should be able to choose whether we'd prefer performance or accuracy).

My suggestion is that ruby-units should use mathn if it is already in the namespace, rather than requiring it internally. Users of ruby-units that prefer the accuracy that comes with mathn will need to require mathn explicitly. Other users, such as us, who prefer performance over accuracy and who need to fix unintended side-effects such as what we're getting with Rgeo, will simply not require mathn.

@jasonhutchens

Worth closing this; the issue will not be resolved within ruby-units.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 23, 2012
  1. Match Math.sqrt to default behaviour with Integers

    Aaron Todd authored
    I realise that the mathn library changes this, but I think most developers rely on Math.sqrt returning a float like the default math.rb library. As such when we use ruby-unit + other gems that rely on Math.sqrt returning a Float we can get issues (alchemist, or rgeo for example).
This page is out of date. Refresh to see the latest.
Showing with 7 additions and 1 deletion.
  1. +7 −1 lib/ruby_units/math.rb
View
8 lib/ruby_units/math.rb
@@ -7,11 +7,17 @@ module Math
alias :unit_sqrt :sqrt
# @return [Numeric]
def sqrt(n)
- if Unit === n
+ result = if Unit === n
(n**(Rational(1,2))).to_unit
else
unit_sqrt(n)
end
+
+ if result.is_a?(Fixnum)
+ result.to_f
+ else
+ result
+ end
end
# @return [Numeric]
module_function :unit_sqrt
Something went wrong with that request. Please try again.