def number_with_precision(number, options = {})
options.symbolize_keys!
number = begin
Float(number)
rescue ArgumentError, TypeError
if options[:raise]
raise InvalidNumberError, number
else
return number
end
end
defaults = I18n.translate('number.format''number.format', :locale => options[:locale], :default => {})
precision_defaults = I18n.translate('number.precision.format''number.precision.format', :locale => options[:locale], :default => {})
defaults = defaults.merge(precision_defaults)
options = options.reverse_merge(defaults)
precision = options.delete :precision
significant = options.delete :significant
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
if significant and precision > 0
if number == 0
digits, rounded_number = 1, 0
else
digits = (Math.log10(number.abs) + 1).floor
rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision)
end
precision = precision - digits
precision = precision > 0 ? precision : 0
else
rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision
end
formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
if strip_insignificant_zeros
escaped_separator = Regexp.escape(options[:separator])
formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '').html_safe
else
formatted_number
end
end