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