Method: ActiveSupport::NumberHelper#number_to_rounded

Defined in:
activesupport/lib/active_support/number_helper.rb

#number_to_rounded(number, options = {}) ⇒ Object

Formats a number with the specified level of :precision (e.g., 112.32 has a precision of 2 if :significant is false, and 5 if :significant is true). You can customize the format in the options hash.

Options

  • :locale - Sets the locale to be used for formatting (defaults to current locale).

  • :precision - Sets the precision of the number (defaults to 3).

  • :significant - If true, precision will be the # of significant_digits. If false, the # of fractional digits (defaults to false).

  • :separator - Sets the separator between the fractional and integer digits (defaults to “.”).

  • :delimiter - Sets the thousands delimiter (defaults to “”).

  • :strip_insignificant_zeros - If true removes insignificant zeros after the decimal separator (defaults to false).

Examples

number_to_rounded(111.2345)                                  # => 111.235
number_to_rounded(111.2345, precision: 2)                    # => 111.23
number_to_rounded(13, precision: 5)                          # => 13.00000
number_to_rounded(389.32314, precision: 0)                   # => 389
number_to_rounded(111.2345, significant: true)               # => 111
number_to_rounded(111.2345, precision: 1, significant: true) # => 100
number_to_rounded(13, precision: 5, significant: true)       # => 13.000
number_to_rounded(111.234, locale: :fr)                      # => 111,234

number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
# => 13

number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
# => 1.111,23

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'activesupport/lib/active_support/number_helper.rb', line 342

def number_to_rounded(number, options = {})
  return number unless valid_float?(number)
  number  = Float(number)
  options = options.symbolize_keys

  defaults = format_options(options[:locale], :precision)
  options  = defaults.merge!(options)

  precision = options.delete :precision
  significant = options.delete :significant
  strip_insignificant_zeros = options.delete :strip_insignificant_zeros

  if significant && precision > 0
    if number == 0
      digits, rounded_number = 1, 0
    else
      digits = (Math.log10(number.abs) + 1).floor
      multiplier = 10 ** (digits - precision)
      rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new(multiplier.to_f.to_s)).round.to_f * multiplier
      digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
    end
    precision -= digits
    precision = 0 if precision < 0 # don't let it be negative
  else
    rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
    rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
  end
  formatted_number = self.number_to_delimited("%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/, '')
  else
    formatted_number
  end
end