Adrian Rotama
Adrian Rotama

Reputation: 311

Rails rounding decimal to the nearest power of ten

I'm looking for a rails function that could return the number to the nearest power of ten(10,100,1000), and also need to support number between 0 and 1 (0.1, 0.01, 0.001):

round(9) = 10  
round(19) = 10  
round(79) = 100  
round(812.12) = 1000  

round(0.0321) = 0.01  
round(0.0921) = 0.1

I've looking on : Round number down to nearest power of ten
the accepted answer using the length of the string, that can't applied to number between 0 and 1.

updated Round up to nearest power of 10 this one seems great. But I still can't make it work in rails.

Upvotes: 1

Views: 811

Answers (5)

Maciej Nędza
Maciej Nędza

Reputation: 392

Let's simplify your problem to the following form - let the input numbers be in the range [0.1, 1), how would rounding of such numbers look like then?

The answer would be simple - for numbers smaller than 0.5 we would return the number 0.1, for larger numbers it would be 1.0.

All we have to do is to make sure that our number will be in that range. We will "move" decimal separator and remember how many moves we made in second variable. This operation is called normalization.

def normalize(fraction)
    exponent = 0

    while fraction < (1.0/10.0)
        fraction *= 10.0
        exponent -= 1
    end

    while fraction >= 1.0
        fraction /= 10.0
        exponent += 1
    end

    [fraction, exponent]
end

Using above code you can represent any floating number as a pair of normalized fraction and exponent in base 10. To recreate original number we will move decimal point in opposite direction using formula

original = normalized * base^{exponent}

With data property normalized we can use it in our simple rounding method like that:

def round(number)
    fraction, exponent = normalize(number)

    if fraction < 0.5
        0.1 * 10 ** exponent
    else
        1.0 * 10 ** exponent
    end
end

Upvotes: 1

needprayfornotaxes
needprayfornotaxes

Reputation: 131

class Numeric
  def name
    def helper x, y, z
      num = self.abs
      r = 1
      while true
        result = nil
        if num.between?(x, y)
          if num >= y/2.0 
            result = y.round(r+1) 
          else
            result = x.round(r)
          end
          return self.negative? ? -result : result
        end
        x *= z; y *= z; r += 1
      end
    end

    if self.abs < 1
      helper 0.1, 1, 0.1
    else 
      helper 1, 10, 10
    end
  end
end

Example

-0.049.name # => -0.01
12.name # => 10

and so on, you are welcome!

Upvotes: 0

Ravi Teja Dandu
Ravi Teja Dandu

Reputation: 476

I'm not sure about any function which automatically rounds the number to the nearest power of ten. You can achieve it by running the following code:

def rounded_to_nearest_power_of_ten(value)
    abs_value = value.abs
    power_of_ten = Math.log10(abs_value)
    upper_limit = power_of_ten.ceil
    lower_limit = power_of_ten.floor
    nearest_value = (10**upper_limit - abs_value).abs > (10**lower_limit - abs_value).abs ? 10**lower_limit : 10**upper_limit
    value > 0 ? nearest_value : -1*nearest_value
end

Hope this helps.

Upvotes: 2

Try this:

def round_tenth(a)
    if a.to_f >= 1
      return 10 ** (a.floor.to_s.size - ( a.floor.to_s[0].to_i > 4 ? 0 : 1))
    end
    #a = 0.0392
    c = a.to_s[2..a.to_s.length] 
    b = 0
    c.split('').each_with_index do |s, i|
      if s.to_i != 0
        b = i + 1
        break
      end
    end
    arr = Array.new(100, 0)
    if c[b-1].to_i > 4 
      b -= 1
      if b == 0
        return 1
      end
    end
    arr[b-1] = 1
    return ("0." + arr.join()).to_f
  end

Upvotes: 1

if the number is >= 1.0, this should work.

10 ** (num.floor.to_s.size - ( num.floor.to_s[0].to_i > 4 ? 0 : 1))

Upvotes: 1

Related Questions