lare_round 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +7 -8
- data/README.md +2 -2
- data/Rakefile +2 -3
- data/lare_round.gemspec +26 -13
- data/lib/lare_round.rb +107 -36
- data/lib/lare_round/version.rb +1 -1
- data/test/lare_round_test.rb +94 -59
- data/test/test_helper.rb +8 -4
- metadata +55 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22cc87361ca388e9fea449cc3fc775bba6c4869a
|
4
|
+
data.tar.gz: 5b837592bedcd9da1f528fdabf5a328896422860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92fc9fcefcdb98717afbd19cc8b2c2423f23dd53e2e195af746fe50183422c6518abe76a31260a1d1ef0d77fde661f27cd4d251841e3c6222e6e8da841a6ff15
|
7
|
+
data.tar.gz: cbd9d9df3a74c4f7a7a66d49f60923468e47066ffd615f421e055b732798c80b627c32f7ff12b03df05210cf5f04b9da51e41d32263f2d9c3d1daa1e9f6eae01
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -93,13 +93,13 @@ Item (unrounded)| Price (unrounded) | LareRound | Financial
|
|
93
93
|
tax ( 8.23%) | 0.823 | 0.82 | 0.83
|
94
94
|
**Total** | **10.823** | **10.82** | **10.83**
|
95
95
|
|
96
|
-
*
|
96
|
+
* refactoring ^^
|
97
97
|
|
98
98
|
## Installation
|
99
99
|
|
100
100
|
Add this line to your application's Gemfile:
|
101
101
|
|
102
|
-
gem 'lare_round',
|
102
|
+
gem 'lare_round', '~> 0.0.1'
|
103
103
|
|
104
104
|
And then execute:
|
105
105
|
|
data/Rakefile
CHANGED
data/lare_round.gemspec
CHANGED
@@ -4,21 +4,34 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'lare_round/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'lare_round'
|
8
8
|
spec.version = LareRound::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
spec.authors = ['Carsten Wirth']
|
10
|
+
spec.email = ['carsten.wirth@blacklane.com']
|
11
|
+
|
12
|
+
spec.description = <<-DESCRIPTION
|
13
|
+
A collection of BigDecimal items e.g. invoice items can be rounded for
|
14
|
+
displaying them in views. Rounding may apply a rounding error to the
|
15
|
+
items such as the summed up rounded items will show deviation towards
|
16
|
+
an invoice total with summed unrounded items. Which might cause
|
17
|
+
confusion for customers and finance departments alike.
|
18
|
+
|
19
|
+
Application of the largest remainder method can help to preserve the
|
20
|
+
total sum for fractionated parts thus eliminating this confusion.
|
21
|
+
DESCRIPTION
|
22
|
+
|
23
|
+
spec.summary = 'gem for rounding BigDecimal items by preserving its sum'
|
24
|
+
spec.homepage = ''
|
25
|
+
spec.license = 'MIT'
|
16
26
|
|
17
27
|
spec.files = `git ls-files`.split($/)
|
18
|
-
spec.executables = spec.files.grep(
|
19
|
-
spec.test_files = spec.files.grep(
|
20
|
-
spec.require_paths = [
|
28
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
29
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
30
|
+
spec.require_paths = ['lib']
|
21
31
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
32
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
33
|
+
spec.add_development_dependency 'rake'
|
34
|
+
spec.add_development_dependency 'rubocop'
|
35
|
+
spec.add_development_dependency 'minitest'
|
36
|
+
spec.add_development_dependency 'simplecov'
|
24
37
|
end
|
data/lib/lare_round.rb
CHANGED
@@ -1,54 +1,125 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
|
3
3
|
module LareRound
|
4
|
+
def self.round(values, precision)
|
5
|
+
# although it is the senders responsibility to ensure that correct messages
|
6
|
+
# are sent to this module it might not be quite obvious so i provide some
|
7
|
+
# help here with errors if input is invalid
|
8
|
+
array_of_values = values.is_a?(Hash) ? values.values : values
|
9
|
+
handle_value_errors(array_of_values)
|
10
|
+
handle_precision_errors(precision)
|
4
11
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
values
|
16
|
-
|
12
|
+
process(values, precision)
|
13
|
+
end
|
14
|
+
|
15
|
+
# StandardError for dealing with application level errors
|
16
|
+
class LareRoundError < StandardError; end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.process(values, precision)
|
21
|
+
if values.is_a? Hash
|
22
|
+
process_hash(values, precision)
|
23
|
+
else
|
24
|
+
round_array_of_values(values, precision)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.process_hash(values, precision)
|
29
|
+
rounded_values = round_array_of_values(values.values, precision)
|
30
|
+
values.tap do |hash|
|
31
|
+
hash.keys.each_with_index do |key, index|
|
32
|
+
hash[key] = rounded_values[index]
|
17
33
|
end
|
18
|
-
return values
|
19
34
|
end
|
20
35
|
end
|
21
36
|
|
22
|
-
|
23
|
-
|
37
|
+
def self.handle_value_errors(values)
|
38
|
+
fail LareRoundError, 'values must not be nil' if values.nil?
|
39
|
+
fail LareRoundError, 'values must not be empty' if values.empty?
|
40
|
+
fail LareRoundError, 'values must be an array' unless values.is_a? Array
|
24
41
|
|
42
|
+
numbers_invalid = values.map { |i| i.is_a? Numeric }
|
43
|
+
.reject { |i| i == true }.size
|
44
|
+
if numbers_invalid > 0
|
45
|
+
error = <<-ERROR.strip.gsub(/\s+/, ' ')
|
46
|
+
values contains not numeric values (#{numbers_invalid})
|
47
|
+
ERROR
|
48
|
+
fail LareRoundError, error
|
49
|
+
end
|
50
|
+
|
51
|
+
if values.map { |i| i.is_a? BigDecimal }.reject { |i| i == true }.size > 0
|
52
|
+
warning = <<-WARNING.strip.gsub(/\s+/, ' ')
|
53
|
+
values contains non decimal values,
|
54
|
+
you might loose precision or even get wrong rounding results
|
55
|
+
WARNING
|
56
|
+
warn warning
|
57
|
+
end
|
25
58
|
end
|
26
59
|
|
27
|
-
|
28
|
-
|
29
|
-
raise LareRoundError.new("array_of_values must be an array") unless array_of_values.is_a? Array
|
30
|
-
number_of_invalid_values = array_of_values.map{|i| i.is_a? Numeric}.reject{|i| i == true}.size
|
31
|
-
raise LareRoundError.new("values contains not numeric values (#{number_of_invalid_values})") if number_of_invalid_values > 0
|
32
|
-
warn "values contains non decimal values, you might loose precision or even get wrong rounding results" if array_of_values.map{|i| i.is_a? BigDecimal}.reject{|i| i == true}.size > 0
|
33
|
-
|
34
|
-
#prevention of can't omit precision for a Rational
|
35
|
-
decimal_shift = BigDecimal.new (10 ** precision.to_i)
|
36
|
-
rounded_total = array_of_values.reduce(:+).round(precision) * decimal_shift
|
37
|
-
array_of_values = array_of_values.map{|v| ((v.is_a? BigDecimal) ? v : BigDecimal.new(v.to_s))}
|
38
|
-
unrounded_values = array_of_values.map{|v| v * decimal_shift }
|
60
|
+
def self.handle_precision_errors(precision)
|
61
|
+
fail LareRoundError, 'precision must not be nil' if precision.nil?
|
39
62
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# elsewise if negative
|
44
|
-
rounded_values = array_of_values.map{|v| v < 0 ? v.round(precision, BigDecimal::ROUND_UP) * decimal_shift : v.round(precision, BigDecimal::ROUND_DOWN) * decimal_shift }
|
63
|
+
unless precision.is_a? Numeric
|
64
|
+
fail LareRoundError, 'precision must be a number'
|
65
|
+
end
|
45
66
|
|
46
|
-
|
47
|
-
|
48
|
-
|
67
|
+
if precision < 0
|
68
|
+
fail LareRoundError, 'precision must be greater or equal to 0'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Struct.new(
|
73
|
+
'IntermediaryResults',
|
74
|
+
:decimal_shift,
|
75
|
+
:rounded_total,
|
76
|
+
:array_of_values,
|
77
|
+
:unrounded_values,
|
78
|
+
:precision,
|
79
|
+
:rounded_values
|
80
|
+
)
|
81
|
+
|
82
|
+
def self.round_array_of_values(array_of_values, precision)
|
83
|
+
mrc = Struct::IntermediaryResults.new
|
84
|
+
mrc.precision = precision
|
85
|
+
mrc.decimal_shift = BigDecimal.new(10**precision.to_i)
|
86
|
+
mrc.rounded_total = array_of_values.reduce(:+)
|
87
|
+
.round(precision) * mrc.decimal_shift
|
88
|
+
mrc.array_of_values = array_of_values.map do |v|
|
89
|
+
((v.is_a? BigDecimal) ? v : BigDecimal.new(v.to_s))
|
90
|
+
end
|
91
|
+
mrc.unrounded_values = array_of_values.map { |v| v * mrc.decimal_shift }
|
92
|
+
|
93
|
+
largest_remainder_method(mrc)
|
94
|
+
|
95
|
+
mrc.rounded_values
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.largest_remainder_method(mrc)
|
99
|
+
mrc.rounded_values = mrc.array_of_values.map do |v|
|
100
|
+
largest_remainder_round(v, mrc)
|
49
101
|
end
|
50
102
|
|
51
|
-
|
103
|
+
until mrc.rounded_values.reduce(:+) >= mrc.rounded_total
|
104
|
+
fractions = mrc.unrounded_values.zip(mrc.rounded_values).map do |x, y|
|
105
|
+
x - y
|
106
|
+
end
|
107
|
+
mrc.rounded_values[fractions.index(fractions.max)] += 1
|
108
|
+
end
|
109
|
+
|
110
|
+
mrc.rounded_values.map! { |v| v / mrc.decimal_shift }
|
52
111
|
end
|
53
112
|
|
113
|
+
def self.largest_remainder_round(v, mrc)
|
114
|
+
# items needed to be rounded down if positiv:
|
115
|
+
# 0.7 + 0.7 + 0.7 = ( 2.1 ).round(0) = 2
|
116
|
+
# (0.7).round(0) + (0.7).round(0) + (0.7).round(0) = 1 + 1 + 1 = 3
|
117
|
+
# elsewise if negative
|
118
|
+
rounding_strategy = if v < 0
|
119
|
+
BigDecimal::ROUND_UP
|
120
|
+
else
|
121
|
+
BigDecimal::ROUND_DOWN
|
122
|
+
end
|
123
|
+
v.round(mrc.precision, rounding_strategy) * mrc.decimal_shift
|
124
|
+
end
|
54
125
|
end
|
data/lib/lare_round/version.rb
CHANGED
data/test/lare_round_test.rb
CHANGED
@@ -2,115 +2,150 @@ require_relative 'test_helper'
|
|
2
2
|
require 'bigdecimal'
|
3
3
|
require 'securerandom'
|
4
4
|
|
5
|
-
class LareRoundTest < MiniTest::
|
5
|
+
class LareRoundTest < MiniTest::Spec
|
6
|
+
def test_has_static_method_round
|
7
|
+
assert_equal(true, LareRound.respond_to?(:round))
|
8
|
+
end
|
6
9
|
|
7
|
-
def
|
8
|
-
|
10
|
+
def create_big_decimal(precision, digit)
|
11
|
+
BigDecimal.new('0.' + '3' * precision + "#{digit}")
|
9
12
|
end
|
10
13
|
|
11
14
|
(1..9).each do |digit|
|
12
15
|
(1..23).each do |items|
|
13
16
|
(0..10).each do |precision|
|
14
17
|
|
15
|
-
method_name =
|
18
|
+
method_name = <<-TESTMETHOD.strip.gsub(/\s+/, '_')
|
19
|
+
test #{items} items with last digit of #{digit}
|
20
|
+
should sum up to rounded total of BigDecimal items
|
21
|
+
with precision of #{precision} if passed as array
|
22
|
+
TESTMETHOD
|
16
23
|
define_method method_name do
|
17
|
-
|
18
|
-
arr = Array.new(items){decimal}
|
24
|
+
arr = Array.new(items) { create_big_decimal(precision, digit) }
|
19
25
|
rounded_total = arr.reduce(:+).round(precision)
|
20
|
-
assert_equal(
|
26
|
+
assert_equal(
|
27
|
+
rounded_total,
|
28
|
+
LareRound.round(arr, precision).reduce(:+).round(precision)
|
29
|
+
)
|
21
30
|
end
|
22
31
|
|
23
|
-
method_name =
|
32
|
+
method_name = <<-TESTMETHOD.strip.gsub(/\s+/, '_')
|
33
|
+
test #{items} rounded items with last digit of #{digit}
|
34
|
+
should sum up to rounded total of BigDecimal items
|
35
|
+
with precision of #{precision} if passed as hash
|
36
|
+
TESTMETHOD
|
24
37
|
define_method method_name do
|
25
|
-
|
26
|
-
|
38
|
+
hash = Hash[
|
39
|
+
(1..items).map do
|
40
|
+
|x| [x, create_big_decimal(precision, digit)]
|
41
|
+
end
|
42
|
+
]
|
27
43
|
rounded_total = hash.values.reduce(:+).round(precision)
|
28
|
-
assert_equal(
|
44
|
+
assert_equal(
|
45
|
+
rounded_total,
|
46
|
+
LareRound.round(hash, precision).values.reduce(:+).round(precision)
|
47
|
+
)
|
29
48
|
end
|
30
49
|
|
31
|
-
method_name =
|
50
|
+
method_name = <<-TESTMETHOD.strip.gsub(/\s+/, '_')
|
51
|
+
test #{items} rounded items with last digit of #{digit}
|
52
|
+
and precision of #{precision}
|
53
|
+
if passed as hash should not change order
|
54
|
+
TESTMETHOD
|
32
55
|
define_method method_name do
|
33
|
-
|
34
|
-
|
35
|
-
|
56
|
+
hash = Hash[
|
57
|
+
(1..items).map.with_index do |x, i|
|
58
|
+
[x, create_big_decimal(precision, digit) + BigDecimal.new(i)]
|
59
|
+
end
|
60
|
+
]
|
61
|
+
rounded_hash = LareRound.round(hash.clone, precision)
|
36
62
|
hash.keys.each do |key|
|
37
|
-
assert(
|
63
|
+
assert((((hash[key] - rounded_hash[key]) * 10**precision).abs < 1))
|
38
64
|
end
|
39
65
|
end
|
40
66
|
|
41
|
-
method_name =
|
67
|
+
method_name = <<-TESTMETHOD.strip.gsub(/\s+/, '_')
|
68
|
+
test #{items} rounded negative items with last digit of #{digit}
|
69
|
+
should sum up to rounded total of BigDecimal items with precision
|
70
|
+
of #{precision} if passed as array
|
71
|
+
TESTMETHOD
|
42
72
|
define_method method_name do
|
43
|
-
|
44
|
-
|
73
|
+
arr = Array.new(items) do
|
74
|
+
BigDecimal.new(-1 * create_big_decimal(precision, digit))
|
75
|
+
end
|
45
76
|
rounded_total = arr.reduce(:+).round(precision)
|
46
|
-
assert_equal(
|
77
|
+
assert_equal(
|
78
|
+
rounded_total,
|
79
|
+
LareRound.round(arr, precision).reduce(:+).round(precision)
|
80
|
+
)
|
47
81
|
end
|
48
82
|
|
49
|
-
method_name =
|
83
|
+
method_name = <<-TESTMETHOD.strip.gsub(/\s+/, '_')
|
84
|
+
test #{items} rounded mixed (+/-) items with last digit of #{digit}
|
85
|
+
should sum up to rounded total of BigDecimal items with precision
|
86
|
+
of #{precision} if passed as array
|
87
|
+
TESTMETHOD
|
50
88
|
define_method method_name do
|
51
|
-
|
52
|
-
arr
|
89
|
+
arr = Array.new(items) { create_big_decimal(precision, digit) }
|
90
|
+
arr.map! { |i| SecureRandom.random_number(1).even? ? i : -1 * i }
|
53
91
|
rounded_total = arr.reduce(:+).round(precision)
|
54
|
-
assert_equal(
|
92
|
+
assert_equal(
|
93
|
+
rounded_total,
|
94
|
+
LareRound.round(arr, precision).reduce(:+).round(precision)
|
95
|
+
)
|
55
96
|
end
|
56
|
-
|
57
97
|
end
|
58
98
|
end
|
59
99
|
end
|
60
100
|
|
101
|
+
let(:default_array) { Array.new(3) { BigDecimal.new('0.1234') } }
|
102
|
+
|
61
103
|
def test_should_raise_if_precision_is_nil
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
}
|
67
|
-
assert_equal("precision must not be nil", exception.message)
|
104
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
105
|
+
LareRound.round(default_array, nil)
|
106
|
+
end
|
107
|
+
assert_equal('precision must not be nil', exception.message)
|
68
108
|
end
|
69
109
|
|
70
110
|
def test_should_raise_if_precision_is_less_than_zero
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
-
assert_equal("precision must be greater or equal to 0", exception.message)
|
111
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
112
|
+
LareRound.round(default_array, -1)
|
113
|
+
end
|
114
|
+
assert_equal('precision must be greater or equal to 0', exception.message)
|
77
115
|
end
|
78
116
|
|
79
117
|
def test_should_raise_if_precision_is_not_a_number
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
85
|
-
assert_equal("precision must be a number", exception.message)
|
118
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
119
|
+
LareRound.round(default_array, 'not_a_number')
|
120
|
+
end
|
121
|
+
assert_equal('precision must be a number', exception.message)
|
86
122
|
end
|
87
123
|
|
88
124
|
def test_should_raise_if_values_is_nil
|
89
|
-
exception = assert_raises(LareRound::LareRoundError)
|
90
|
-
LareRound.round(nil,2)
|
91
|
-
|
92
|
-
assert_equal(
|
125
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
126
|
+
LareRound.round(nil, 2)
|
127
|
+
end
|
128
|
+
assert_equal('values must not be nil', exception.message)
|
93
129
|
end
|
94
130
|
|
95
131
|
def test_should_raise_if_values_is_empty
|
96
|
-
exception = assert_raises(LareRound::LareRoundError)
|
97
|
-
LareRound.round([],2)
|
98
|
-
|
99
|
-
assert_equal(
|
132
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
133
|
+
LareRound.round([], 2)
|
134
|
+
end
|
135
|
+
assert_equal('values must not be empty', exception.message)
|
100
136
|
end
|
101
137
|
|
102
138
|
def test_should_raise_if_values_contains_invalid_values
|
103
|
-
exception = assert_raises(LareRound::LareRoundError)
|
104
|
-
LareRound.round([3.2, 1,
|
105
|
-
|
106
|
-
assert_equal(
|
139
|
+
exception = assert_raises(LareRound::LareRoundError) do
|
140
|
+
LareRound.round([3.2, 1, 'not_a_number', Exception.new, nil], 2)
|
141
|
+
end
|
142
|
+
assert_equal('values contains not numeric values (3)', exception.message)
|
107
143
|
end
|
108
144
|
|
109
145
|
def test_should_warn_if_numbers_not_big_decimals
|
110
|
-
|
111
|
-
LareRound.round([1.2132, 12.21212, 323.23],2)
|
146
|
+
_out, err = capture_io do
|
147
|
+
LareRound.round([1.2132, 12.21212, 323.23], 2)
|
112
148
|
end
|
113
|
-
assert_match(/
|
149
|
+
assert_match(/you might loose precision/, err)
|
114
150
|
end
|
115
|
-
|
116
151
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
base_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
5
|
+
lib_dir = File.join(base_dir, 'lib')
|
4
6
|
|
5
7
|
$LOAD_PATH.unshift(lib_dir)
|
6
8
|
|
7
|
-
require '
|
9
|
+
require 'minitest/spec'
|
10
|
+
require 'minitest/autorun'
|
11
|
+
|
8
12
|
require 'lare_round'
|
metadata
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lare_round
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
Carsten Wirth
|
9
|
-
|
7
|
+
- Carsten Wirth
|
10
8
|
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
14
|
name: bundler
|
@@ -40,15 +38,59 @@ dependencies:
|
|
40
38
|
- - ">="
|
41
39
|
- !ruby/object:Gem::Version
|
42
40
|
version: '0'
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |2
|
84
|
+
A collection of BigDecimal items e.g. invoice items can be rounded for
|
85
|
+
displaying them in views. Rounding may apply a rounding error to the
|
86
|
+
items such as the summed up rounded items will show deviation towards
|
87
|
+
an invoice total with summed unrounded items. Which might cause
|
88
|
+
confusion for customers and finance departments alike.
|
89
|
+
|
90
|
+
Application of the largest remainder method can help to preserve the
|
91
|
+
total sum for fractionated parts thus eliminating this confusion.
|
49
92
|
email:
|
50
|
-
-
|
51
|
-
carsten.wirth@blacklane.com
|
93
|
+
- carsten.wirth@blacklane.com
|
52
94
|
executables: []
|
53
95
|
extensions: []
|
54
96
|
extra_rdoc_files: []
|