module ActionView::Helpers::NumberHelper

def number_with_precision(number, options = {})

# => 1.111,23
number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
# => 13
number_with_precision(13, :precision => 5, :significant => true, strip_insignificant_zeros => true)
number_with_precision(111.234, :locale => :fr) # => 111,234
number_with_precision(13, :precision => 5, :significant => true) # => 13.000
number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
number_with_precision(111.2345, :significant => true) # => 111
number_with_precision(389.32314, :precision => 0) # => 389
number_with_precision(13, :precision => 5) # => 13.00000
number_with_precision(111.2345, :precision => 2) # => 111.23
number_with_precision(111.2345) # => 111.235
==== Examples

* :strip_insignificant_zeros - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+)
* :delimiter - Sets the thousands delimiter (defaults to "").
* :separator - Sets the separator between the fractional and integer digits (defaults to ".").
* :significant - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+)
* :precision - Sets the precision of the number (defaults to 3).
* :locale - Sets the locale to be used for formatting (defaults to current locale).
==== Options

You can customize the format in the +options+ hash.
of 2 if +:significant+ is +false+, and 5 if +:significant+ is +true+).
Formats a +number+ with the specified level of :precision (e.g., 112.32 has a precision
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', :locale => options[:locale], :default => {})
  precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {})
  defaults           = defaults.merge(precision_defaults)
  options = options.reverse_merge(defaults)  # Allow the user to unset default values: Eg.: :significant => false
  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.to_s) / BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
      digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
    end
    precision = precision - digits
    precision = precision > 0 ? precision : 0  #don't let it be negative
  else
    rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
  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