blob: 2ad8d49c4edb0e51adf62e70d0139dddf14f6b93 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
# frozen_string_literal: true
module ActiveSupport
module NumberHelper
class RoundingHelper # :nodoc:
attr_reader :options
def initialize(options)
@options = options
end
def round(number)
return number unless precision
number = convert_to_decimal(number)
if significant && precision > 0
round_significant(number)
else
round_without_significant(number)
end
end
def digit_count(number)
return 1 if number.zero?
(Math.log10(absolute_number(number)) + 1).floor
end
private
def round_without_significant(number)
number = number.round(precision)
number = number.to_i if precision == 0 && number.finite?
number = number.abs if number.zero? # prevent showing negative zeros
number
end
def round_significant(number)
return 0 if number.zero?
digits = digit_count(number)
multiplier = 10**(digits - precision)
(number / BigDecimal(multiplier.to_f.to_s)).round * multiplier
end
def convert_to_decimal(number)
case number
when Float, String
BigDecimal(number.to_s)
when Rational
BigDecimal(number, digit_count(number.to_i) + precision)
else
number.to_d
end
end
def precision
options[:precision]
end
def significant
options[:significant]
end
def absolute_number(number)
number.respond_to?(:abs) ? number.abs : number.to_d.abs
end
end
end
end
|