numerals 0.0.0
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 +7 -0
- data/.gitignore +22 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +24 -0
- data/Rakefile +19 -0
- data/lib/numerals/conversions/bigdecimal.rb +30 -0
- data/lib/numerals/conversions/float.rb +226 -0
- data/lib/numerals/conversions/flt.rb +162 -0
- data/lib/numerals/conversions/integer.rb +39 -0
- data/lib/numerals/conversions/rational.rb +32 -0
- data/lib/numerals/conversions.rb +57 -0
- data/lib/numerals/digits.rb +99 -0
- data/lib/numerals/formatting/digits_definition.rb +75 -0
- data/lib/numerals/formatting/options.rb +84 -0
- data/lib/numerals/numeral.rb +650 -0
- data/lib/numerals/rounding.rb +229 -0
- data/lib/numerals/support.rb +10 -0
- data/lib/numerals/version.rb +3 -0
- data/lib/numerals.rb +12 -0
- data/numerals.gemspec +26 -0
- data/test/data.yaml +101 -0
- data/test/helper.rb +40 -0
- data/test/test_digits_definition.rb +110 -0
- data/test/test_float_conversions.rb +58 -0
- data/test/test_flt_conversions.rb +277 -0
- data/test/test_integer_conversions.rb +50 -0
- data/test/test_numeral.rb +366 -0
- data/test/test_rational_conversions.rb +75 -0
- data/test/test_rounding.rb +77 -0
- metadata +138 -0
@@ -0,0 +1,277 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
require 'numerals'
|
4
|
+
include Numerals
|
5
|
+
|
6
|
+
class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
|
7
|
+
|
8
|
+
def test_special_binary
|
9
|
+
|
10
|
+
context = Flt::BinNum.context = Flt::BinNum::FloatContext
|
11
|
+
type = Flt::BinNum
|
12
|
+
|
13
|
+
assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan)
|
14
|
+
assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[:exact, base: 2])
|
15
|
+
assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[:exact, base: 10])
|
16
|
+
assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[precision: 10, base: 10])
|
17
|
+
assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :free)
|
18
|
+
|
19
|
+
assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity)
|
20
|
+
assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[:exact, base: 2])
|
21
|
+
assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[:exact, base: 10])
|
22
|
+
assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[precision: 10, base: 10])
|
23
|
+
assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :free)
|
24
|
+
|
25
|
+
assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1))
|
26
|
+
assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[:exact, base: 2])
|
27
|
+
assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[:exact, base: 10])
|
28
|
+
assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[precision: 10, base: 10])
|
29
|
+
assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :free)
|
30
|
+
|
31
|
+
assert Conversions.numeral_to_number(Numeral.nan, type).nan?
|
32
|
+
assert_equal context.infinity, Conversions.numeral_to_number(Numeral.infinity, type)
|
33
|
+
assert_equal context.infinity(-1), Conversions.numeral_to_number(Numeral.infinity(-1), type)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_exact_binary
|
37
|
+
one = nil
|
38
|
+
context = Flt::BinNum::FloatContext
|
39
|
+
Flt::BinNum.context(context) do
|
40
|
+
one = Flt::BinNum(1, :fixed)
|
41
|
+
end
|
42
|
+
rounding = Rounding[:exact, base: 10]
|
43
|
+
assert_equal Numeral[1, point: 1],
|
44
|
+
Conversions.number_to_numeral(one, :fixed, rounding)
|
45
|
+
assert_equal Numeral[1, point: 1, sign: -1],
|
46
|
+
Conversions.number_to_numeral(-one, :fixed, rounding)
|
47
|
+
|
48
|
+
rounding_2 = Rounding[:exact, base: 2]
|
49
|
+
assert_equal Numeral[1, point: 1, base: 2],
|
50
|
+
Conversions.number_to_numeral(one, :fixed, rounding_2)
|
51
|
+
assert_equal Numeral[1, point: 1, sign: -1, base: 2],
|
52
|
+
Conversions.number_to_numeral(-one, :fixed, rounding_2)
|
53
|
+
|
54
|
+
[0.1, 0.01, 0.001, 1/3.0, 10/3.0, 100/3.0, Math::PI,
|
55
|
+
0.5, 123.0, 123.45, 1.23E32, 1.23E-32].each do |x|
|
56
|
+
[x, -x].each do |y|
|
57
|
+
y = Flt::BinNum(y)
|
58
|
+
numeral = exact_decimal(y)
|
59
|
+
rounding = Rounding[:exact, base: 10]
|
60
|
+
assert_equal numeral, Conversions.number_to_numeral(y, :fixed, rounding),
|
61
|
+
"#{y} to base 10 exact numeral"
|
62
|
+
assert_equal y, Conversions.numeral_to_number(numeral, context),
|
63
|
+
"#{x} base 10 numeral to float"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_conversions_by_context
|
69
|
+
Flt::DecNum.context(precision: 20) do
|
70
|
+
numeral = Numeral[1, point: 0]
|
71
|
+
context = Flt::DecNum::ExtendedContext
|
72
|
+
converted = Conversions.numeral_to_number(numeral, context, :fixed)
|
73
|
+
assert_equal Flt::DecNum('0.100000000'), converted
|
74
|
+
assert_equal 9, converted.number_of_digits
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_conversions_by_class
|
79
|
+
Flt::DecNum.context(precision: 9) do
|
80
|
+
numeral = Numeral[1, point: 0]
|
81
|
+
converted = Conversions.numeral_to_number(numeral, Flt::DecNum, :fixed)
|
82
|
+
assert_equal Flt::DecNum('0.100000000'), converted
|
83
|
+
assert_equal 9, converted.number_of_digits
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def test_equidistiant_nearest
|
89
|
+
# In IEEEDoubleContext
|
90
|
+
# 1E23 is equidistant from 2 Floats: lo & hi
|
91
|
+
# one or the other will be chosen based on the rounding mode
|
92
|
+
|
93
|
+
context = Flt::BinNum::IEEEDoubleContext
|
94
|
+
|
95
|
+
# 1E23
|
96
|
+
numeral = Numeral[1, point: 24]
|
97
|
+
# 9.999999999999999E22
|
98
|
+
numeral_lo = Numeral[[9]*16, point: 23]
|
99
|
+
# 1.0000000000000001E23
|
100
|
+
numeral_hi = Numeral[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, point: 24]
|
101
|
+
|
102
|
+
lo = hi = nil
|
103
|
+
Flt::BinNum.context(context) do
|
104
|
+
lo = Flt::BinNum('0x1.52d02c7e14af6p+76', :fixed)
|
105
|
+
hi = Flt::BinNum('0x1.52d02c7e14af7p+76', :fixed)
|
106
|
+
end
|
107
|
+
|
108
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
109
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
110
|
+
assert_equal lo, x
|
111
|
+
end
|
112
|
+
# x = Conversions.numeral_to_number(numeral, context[rounding: :half_even], :fixed)
|
113
|
+
|
114
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
115
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
116
|
+
assert_equal lo, x
|
117
|
+
end
|
118
|
+
|
119
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
120
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
121
|
+
assert_equal hi, x
|
122
|
+
end
|
123
|
+
|
124
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
125
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
126
|
+
assert_equal -lo, x
|
127
|
+
end
|
128
|
+
# x = Conversions.numeral_to_number(numeral, context[rounding: :half_even], :fixed)
|
129
|
+
|
130
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
131
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
132
|
+
assert_equal -lo, x
|
133
|
+
end
|
134
|
+
|
135
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
136
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
137
|
+
assert_equal -hi, x
|
138
|
+
end
|
139
|
+
|
140
|
+
rounding = Rounding[:exact]
|
141
|
+
|
142
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
143
|
+
assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
|
144
|
+
end
|
145
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
146
|
+
assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding)
|
147
|
+
end
|
148
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
149
|
+
assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
|
150
|
+
end
|
151
|
+
|
152
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
153
|
+
assert_equal numeral, Conversions.number_to_numeral(hi, :free, rounding)
|
154
|
+
end
|
155
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
156
|
+
assert_equal numeral_hi, Conversions.number_to_numeral(hi, :free, rounding)
|
157
|
+
end
|
158
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
159
|
+
assert_equal numeral_hi, Conversions.number_to_numeral(hi, :free, rounding)
|
160
|
+
end
|
161
|
+
|
162
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
163
|
+
assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
|
164
|
+
end
|
165
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
166
|
+
assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding)
|
167
|
+
end
|
168
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
169
|
+
assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
|
170
|
+
end
|
171
|
+
|
172
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
173
|
+
assert_equal -numeral, Conversions.number_to_numeral(-hi, :free, rounding)
|
174
|
+
end
|
175
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
176
|
+
assert_equal -numeral_hi, Conversions.number_to_numeral(-hi, :free, rounding)
|
177
|
+
end
|
178
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
179
|
+
assert_equal -numeral_hi, Conversions.number_to_numeral(-hi, :free, rounding)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_single_nearest
|
184
|
+
# In IEEEDoubleContext
|
185
|
+
# 64.1 between the floats lo, hi, but is closer to lo
|
186
|
+
# So there's a closet Float that should be chosen for rounding
|
187
|
+
|
188
|
+
context = Flt::BinNum::IEEEDoubleContext
|
189
|
+
|
190
|
+
numeral = Numeral[6, 4, 1, point: 2]
|
191
|
+
numeral_lo = Numeral[6, 4, 0, 9, 9, 9 ,9, 9, 9, 9, 9, 9, 9, 9, 9, 9, point: 2]
|
192
|
+
|
193
|
+
lo = hi = nil
|
194
|
+
Flt::BinNum.context(context) do
|
195
|
+
lo = Flt::BinNum('0x1.0066666666666p+6', :fixed) # this is nearer to the 64.1 Float
|
196
|
+
hi = Flt::BinNum('0x1.0066666666667p+6', :fixed)
|
197
|
+
end
|
198
|
+
|
199
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
200
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
201
|
+
assert_equal lo, x
|
202
|
+
end
|
203
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
204
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
205
|
+
assert_equal lo, x
|
206
|
+
end
|
207
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
208
|
+
x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
|
209
|
+
assert_equal lo, x
|
210
|
+
end
|
211
|
+
|
212
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
213
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
214
|
+
assert_equal -lo, x
|
215
|
+
end
|
216
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
217
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
218
|
+
assert_equal -lo, x
|
219
|
+
end
|
220
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
221
|
+
x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
|
222
|
+
assert_equal -lo, x
|
223
|
+
end
|
224
|
+
|
225
|
+
rounding = Rounding[:exact]
|
226
|
+
rounding_16 = Rounding[:half_even, precision: 16]
|
227
|
+
|
228
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
229
|
+
assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
|
230
|
+
end
|
231
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
232
|
+
assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
|
233
|
+
end
|
234
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
235
|
+
assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
|
236
|
+
end
|
237
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
238
|
+
assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
|
239
|
+
end
|
240
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
241
|
+
assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
|
242
|
+
end
|
243
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
244
|
+
assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
|
245
|
+
end
|
246
|
+
|
247
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
248
|
+
assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
|
249
|
+
end
|
250
|
+
Flt::BinNum.context(context, rounding: :half_even) do
|
251
|
+
assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
|
252
|
+
end
|
253
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
254
|
+
assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
|
255
|
+
end
|
256
|
+
Flt::BinNum.context(context, rounding: :half_down) do
|
257
|
+
assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
|
258
|
+
end
|
259
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
260
|
+
assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
|
261
|
+
end
|
262
|
+
Flt::BinNum.context(context, rounding: :half_up) do
|
263
|
+
assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
def exact_decimal(x)
|
269
|
+
Flt::DecNum.context(exact: true){
|
270
|
+
Flt::BinNum.context(Flt::BinNum::FloatContext){
|
271
|
+
d = Flt::BinNum(x).to_decimal_exact
|
272
|
+
Numeral[d.coefficient.to_s.chars.map(&:to_i), sign: d.sign, point: d.fractional_exponent, normalize: :exact]
|
273
|
+
}
|
274
|
+
}
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
require 'numerals'
|
4
|
+
include Numerals
|
5
|
+
|
6
|
+
class TestIntegerConversions < Test::Unit::TestCase # < Minitest::Test
|
7
|
+
|
8
|
+
def test_special
|
9
|
+
assert_raise(ZeroDivisionError){ Conversions.numeral_to_number(Numeral.nan, Integer) }
|
10
|
+
assert_raise(ZeroDivisionError){ Conversions.numeral_to_number(Numeral.infinity, Integer) }
|
11
|
+
assert_raise(ZeroDivisionError){ Conversions.numeral_to_number(Numeral.infinity(-1), Integer) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_integer_to_numeral
|
15
|
+
exact = Rounding[:exact]
|
16
|
+
nine_digits = Rounding[:half_even, precision: 9]
|
17
|
+
|
18
|
+
assert_equal Numeral[1, point: 1], Conversions.number_to_numeral(1)
|
19
|
+
assert_equal Numeral[1, point: 1], Conversions.number_to_numeral(1, exact)
|
20
|
+
assert_equal Numeral[1, 0, 0, 0, 0, 0, 0, 0, 0, point: 1],
|
21
|
+
Conversions.number_to_numeral(1, nine_digits)
|
22
|
+
|
23
|
+
assert_equal Numeral[1, point: 1, sign: -1], Conversions.number_to_numeral(-1)
|
24
|
+
assert_equal Numeral[1, point: 1, sign: -1], Conversions.number_to_numeral(-1, exact)
|
25
|
+
assert_equal Numeral[1, 0, 0, 0, 0, 0, 0, 0, 0, point: 1, sign: -1],
|
26
|
+
Conversions.number_to_numeral(-1, nine_digits)
|
27
|
+
|
28
|
+
assert_equal Numeral[4, 2, point: 2], Conversions.number_to_numeral(42)
|
29
|
+
assert_equal Numeral[4, 2, point: 2], Conversions.number_to_numeral(42, exact)
|
30
|
+
assert_equal Numeral[4, 2, 0, 0, 0, 0, 0, 0, 0, point: 2],
|
31
|
+
Conversions.number_to_numeral(42, nine_digits)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_numeral_to_rational
|
35
|
+
assert_raise IntegerConversion::InvalidConversion do
|
36
|
+
Conversions.numeral_to_number(Numeral[3, point: 0, repeat: 0], Integer)
|
37
|
+
end
|
38
|
+
assert_raise IntegerConversion::InvalidConversion do
|
39
|
+
Conversions.numeral_to_number(Numeral[[3]*9, point: 0, normalize: :approximate], Integer)
|
40
|
+
end
|
41
|
+
assert_raise IntegerConversion::InvalidConversion do
|
42
|
+
Conversions.numeral_to_number(Numeral[1, point: 0], Integer)
|
43
|
+
end
|
44
|
+
assert_equal 1, Conversions.numeral_to_number(Numeral[1, point: 1], Integer)
|
45
|
+
assert_equal -1, Conversions.numeral_to_number(Numeral[1, point: 1, sign: -1], Integer)
|
46
|
+
assert_equal 42,
|
47
|
+
Conversions.numeral_to_number(Numeral[4, 2, point: 2], Integer)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|