Ruby/Rails: How can I display a number in scientific notation?
Asked Answered
O

3

6

I figured this would be an easy one, but I can't find any information about it anywhere. Lets say a user enters 123456. I want to display this in scientific notation. So that would be 1.23456 * 10^5. I figured ruby or rails would have a helper method, like scientific_notation(123456), but I can't find anything. Is this possible?

And to take it a step further, what about processing the number if the user enters scientific notation? For instance, they enter 1.23456x10^6 - rails parses this and stores 123456 in the database.

I realize the second part is a long shot.

Oryx answered 9/7, 2015 at 3:48 Comment(0)
W
9

To convert a number into power of e we can use the % operator.

say x = 123456 then

"%e" %x
=> 1.234560e+05
Waers answered 9/7, 2015 at 3:59 Comment(2)
Awesome! One more question. Lets say its 1200000. It would display as 1.200000e+06. I would like it to remove the extra 00000's. so Just 1.2e+06. Can I set the precision somehow?Oryx
To answer my own question in the last comment, you can do "%.1e" % x, which would give "1.2e+05"Oryx
P
3

To convert an Integer, Bignum or BigDecimal to a scientific number notation, you can use .to_f method.

Here some examples:

# Generate a long number
num = BigDecimal.new('123e+100')
#=> #<BigDecimal:1bca380,'0.123E1003',9(18)> 
num.to_s
#=> "123000000000000....
num.to_f
#=> 1.23e+102

# Convert BigDecimal to integer
int = num.to_i
#=> 123000000000000....
int.class
#=> Bignum
int.to_f
#=> 1.23e+102

In general using .to_f on Integer, Bignum and BigDecimal converts the number in a scientific notation if the number is very long (length > 15).

Prosit answered 22/1, 2016 at 13:9 Comment(1)
The OP stated "I want to display this in scientific notation.", not "I want to display this in scientific notation, if the number is very long." Even the example given was only 6 digits in length. Using the .to_f method does not answer the Question that was asked.Cisterna
T
0

As I don't think the question was completely answered (the notation and possible cut-off for numbers with long fractional part) and I needed something close to the original question, here is my solution.

I'm making use of BigDecimal and extending the class to implement my helper (it should only require changing the method signature and first line of the body if you prefer to extract it into its own module or class)

class BigDecimal
  def to_sci(power_format='*10^%i')
    match_result = to_s.match(/0\.([0-9])([0-9]*)e([+-]?[0-9]*)/)

    int_part = match_result[1]
    float_part = match_result[2]
    exponent = match_result[3].to_i - 1

    significand = if float_part.empty?
                    int_part
                  else
                    "#{int_part}.#{float_part}"
                  end

    formatter = if negative?
                  "-%s#{power_format}"
                else
                  "%s#{power_format}"
                end

    formatter % [significand, exponent]
  end
end

A possible improvement of the code might be to add a precision argument. I've never needed it and therefore did not implement it.

You can also add methods to Integer and Float as shortcuts:

require 'bigdecimal/util'

class Integer
  def to_sci(power_format='*10^%i')
    to_d.to_sci(power_notation)
  end
end

class Float
  def to_sci(power_format='*10^%i')
    to_d.to_sci(power_format)
  end
end

Example usage:

120.to_sci # Output: '1.2*10^2'
120.to_sci('\cdot 10^{%i}') # Output: '1.2\cdot 10^{2}'
0.05.to_sci('x10^%i') # Output: '5x10^-2'

Number from user input

As for the second question of getting numbers from scientific notation from a user (like '1.3x10^3' or '1.3*10^3') one option might be as follows. Please note that this is untested and might break on some edge cases. I'm assuming we have nice users that will only enter valid input like "2.3x10^3", "2.3X10^3", "2.3*10^3" or similar.

def from_sci(str)
  BigDecimal(str.gsub(/[*xX]10\^/, 'e'))
end
Turgid answered 4/11, 2022 at 12:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.