long-decimal 0.00.10 → 0.00.11
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.
- data/VERSION +1 -1
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.html +12 -5
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000136.html +22 -0
- data/doc/classes/LongMath/LongDecimal.html +1624 -0
- data/doc/classes/LongMath/LongDecimal.src/M000061.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000062.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000063.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000064.html +20 -0
- data/doc/classes/LongMath/LongDecimal.src/M000065.html +109 -0
- data/doc/classes/LongMath/LongDecimal.src/M000066.html +34 -0
- data/doc/classes/LongMath/LongDecimal.src/M000067.html +41 -0
- data/doc/classes/LongMath/LongDecimal.src/M000068.html +35 -0
- data/doc/classes/LongMath/LongDecimal.src/M000069.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000070.html +29 -0
- data/doc/classes/LongMath/LongDecimal.src/M000071.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000072.html +38 -0
- data/doc/classes/LongMath/LongDecimal.src/M000073.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000074.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000075.html +20 -0
- data/doc/classes/LongMath/LongDecimal.src/M000076.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000077.html +29 -0
- data/doc/classes/LongMath/LongDecimal.src/M000078.html +46 -0
- data/doc/classes/LongMath/LongDecimal.src/M000079.html +29 -0
- data/doc/classes/LongMath/LongDecimal.src/M000080.html +27 -0
- data/doc/classes/LongMath/LongDecimal.src/M000081.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000083.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000084.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000085.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000086.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000087.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000089.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000090.html +22 -0
- data/doc/classes/LongMath/LongDecimal.src/M000091.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000092.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000093.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000094.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000095.html +29 -0
- data/doc/classes/LongMath/LongDecimal.src/M000096.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000097.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000098.html +34 -0
- data/doc/classes/LongMath/LongDecimal.src/M000099.html +22 -0
- data/doc/classes/LongMath/LongDecimal.src/M000100.html +19 -0
- data/doc/classes/LongMath/LongDecimal.src/M000101.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000102.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000103.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000104.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000105.html +21 -0
- data/doc/classes/LongMath/LongDecimal.src/M000106.html +21 -0
- data/doc/classes/LongMath/LongDecimal.src/M000107.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000108.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000109.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000110.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000111.html +19 -0
- data/doc/classes/LongMath/LongDecimal.src/M000112.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000113.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000114.html +30 -0
- data/doc/classes/LongMath/LongDecimal.src/M000115.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000116.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000117.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000118.html +30 -0
- data/doc/classes/LongMath/LongDecimal.src/M000119.html +23 -0
- data/doc/classes/LongMath/LongDecimal.src/M000120.html +19 -0
- data/doc/classes/LongMath/LongDecimal.src/M000121.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000122.html +47 -0
- data/doc/classes/LongMath/LongDecimal.src/M000123.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000124.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000125.html +47 -0
- data/doc/classes/LongMath/LongDecimal.src/M000126.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000127.html +19 -0
- data/doc/classes/LongMath/LongDecimal.src/M000130.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000131.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000132.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000133.html +18 -0
- data/doc/classes/LongMath/LongDecimal.src/M000134.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.html +797 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000024.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000025.html +28 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000026.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000027.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000028.html +19 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000029.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000030.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000031.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000032.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000033.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000034.html +22 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000035.html +23 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000036.html +23 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000037.html +23 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000038.html +23 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000039.html +35 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000040.html +22 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000041.html +19 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000042.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000043.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000044.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000045.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000046.html +77 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000047.html +36 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000048.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000049.html +23 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000050.html +19 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000051.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000052.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000053.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000054.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000055.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000058.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000059.html +18 -0
- data/doc/classes/LongMath/LongDecimalQuot.src/M000060.html +18 -0
- data/doc/classes/LongMath/Numeric.html +150 -0
- data/doc/classes/LongMath/Numeric.src/M000135.html +18 -0
- data/doc/classes/LongMath.html +70 -37
- data/doc/classes/LongMath.src/M000001.html +19 -0
- data/doc/classes/LongMath.src/M000002.html +18 -0
- data/doc/classes/LongMath.src/M000003.html +18 -0
- data/doc/classes/LongMath.src/M000004.html +19 -0
- data/doc/classes/LongMath.src/M000005.html +18 -0
- data/doc/classes/LongMath.src/M000006.html +32 -0
- data/doc/classes/LongMath.src/M000007.html +32 -0
- data/doc/classes/LongMath.src/M000008.html +19 -0
- data/doc/classes/LongMath.src/M000009.html +43 -0
- data/doc/classes/LongMath.src/M000010.html +19 -0
- data/doc/classes/LongMath.src/M000011.html +73 -0
- data/doc/classes/LongMath.src/M000012.html +35 -0
- data/doc/classes/LongMath.src/M000013.html +50 -0
- data/doc/classes/LongMath.src/M000014.html +47 -0
- data/doc/classes/LongMath.src/M000015.html +22 -0
- data/doc/classes/LongMath.src/M000016.html +25 -0
- data/doc/classes/LongMath.src/M000017.html +107 -0
- data/doc/classes/LongMath.src/M000018.html +21 -0
- data/doc/classes/LongMath.src/M000019.html +30 -0
- data/doc/classes/LongMath.src/M000020.html +30 -0
- data/doc/classes/LongMath.src/M000021.html +115 -0
- data/doc/classes/LongMath.src/M000022.html +22 -0
- data/doc/classes/LongMath.src/M000023.html +18 -0
- data/doc/created.rid +1 -1
- data/doc/files/lib/longdecimal_rb.html +2 -2
- data/doc/fr_method_index.html +108 -111
- data/lib/longdecimal.rb +333 -93
- metadata +139 -2
data/lib/longdecimal.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#
|
2
2
|
# longdecimal.rb -- Arbitrary precision decimals with fixed decimal point
|
3
3
|
#
|
4
|
-
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.
|
5
|
-
# CVS-Label: $Name:
|
4
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.8 2006/03/14 20:25:22 bk1 Exp $
|
5
|
+
# CVS-Label: $Name: PRE_ALPHA_0_11 $
|
6
6
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
7
7
|
#
|
8
8
|
require "complex"
|
@@ -16,7 +16,13 @@ require "bigdecimal"
|
|
16
16
|
# this serves the purpose of an "enum" in C/C++
|
17
17
|
#
|
18
18
|
module LongDecimalRoundingMode
|
19
|
+
|
19
20
|
RoundingModeClass = Struct.new(:name, :num)
|
21
|
+
|
22
|
+
#
|
23
|
+
# enumeration class to express the possible rounding modes that are
|
24
|
+
# supported by LongDecimal
|
25
|
+
#
|
20
26
|
class RoundingModeClass
|
21
27
|
include Comparable
|
22
28
|
|
@@ -47,8 +53,11 @@ module LongDecimalRoundingMode
|
|
47
53
|
end # LongDecimalRoundingMode
|
48
54
|
|
49
55
|
#
|
50
|
-
# helper functions to support LongDecimal and
|
51
|
-
#
|
56
|
+
# LongMath provides some helper functions to support LongDecimal and
|
57
|
+
# LongDecimalQuot, mostly operating on integers. They are used
|
58
|
+
# internally here, but possibly they can be used elsewhere as well.
|
59
|
+
# In addition LongMath provides methods like those in Math, but for
|
60
|
+
# LongDecimal instead of Float.
|
52
61
|
#
|
53
62
|
module LongMath
|
54
63
|
|
@@ -58,8 +67,8 @@ module LongMath
|
|
58
67
|
MAX_EXP_ABLE = Math.log(MAX_FLOATABLE).to_i
|
59
68
|
|
60
69
|
#
|
61
|
-
# helper method: checks if word_len is
|
62
|
-
# number into parts
|
70
|
+
# helper method for internal use: checks if word_len is a reasonable
|
71
|
+
# size for splitting a number into parts
|
63
72
|
#
|
64
73
|
def LongMath.check_word_len(word_len, name="word_len")
|
65
74
|
raise TypeError, "#{name} must be a positive number <= 1024" unless (word_len.kind_of? Fixnum) && word_len > 0 && word_len <= 1024
|
@@ -67,21 +76,22 @@ module LongMath
|
|
67
76
|
end
|
68
77
|
|
69
78
|
#
|
70
|
-
# helper method: checks if parameter x is an Integer
|
79
|
+
# helper method for internal use: checks if parameter x is an Integer
|
71
80
|
#
|
72
81
|
def LongMath.check_is_int(x, name="x")
|
73
82
|
raise TypeError, "#{name}=#{x.inspect} must be Integer" unless x.kind_of? Integer
|
74
83
|
end
|
75
84
|
|
76
85
|
#
|
77
|
-
# helper method: checks if parameter x is a LongDecimal
|
86
|
+
# helper method for internal use: checks if parameter x is a LongDecimal
|
78
87
|
#
|
79
88
|
def LongMath.check_is_ld(x, name="x")
|
80
89
|
raise TypeError, "x=#{x.inspect} must be LongDecimal" unless x.kind_of? LongDecimal
|
81
90
|
end
|
82
91
|
|
83
92
|
#
|
84
|
-
# helper method: checks if parameter x is a
|
93
|
+
# helper method for internal use: checks if parameter x is a
|
94
|
+
# reasonable value for the precision (scale) of a LongDecimal
|
85
95
|
#
|
86
96
|
def LongMath.check_is_prec(prec, name="prec")
|
87
97
|
check_is_int(prec, "prec")
|
@@ -89,19 +99,21 @@ module LongMath
|
|
89
99
|
end
|
90
100
|
|
91
101
|
#
|
92
|
-
# helper method: checks if parameter x is a
|
102
|
+
# helper method for internal use: checks if parameter x is a
|
103
|
+
# rounding mode (instance of RoundingModeClass)
|
93
104
|
#
|
94
105
|
def LongMath.check_is_mode(mode, name="mode")
|
95
106
|
raise TypeError, "#{name}=#{mode.inspect} must be legal rounding mode" unless mode.kind_of? RoundingModeClass
|
96
107
|
end
|
97
108
|
|
98
109
|
#
|
99
|
-
# split number x into parts of word_len bits each
|
100
|
-
#
|
110
|
+
# split number (Integer) x into parts of word_len bits each such
|
111
|
+
# that the concatenation of these parts as bit patterns is x
|
112
|
+
# (the opposite of merge_from_words)
|
101
113
|
#
|
102
114
|
def LongMath.split_to_words(x, word_len = 32)
|
103
115
|
check_word_len(word_len)
|
104
|
-
check_is_int(x)
|
116
|
+
check_is_int(x, "x")
|
105
117
|
m = x.abs
|
106
118
|
s = (x <=> 0)
|
107
119
|
bit_pattern = (1 << word_len) - 1
|
@@ -119,6 +131,7 @@ module LongMath
|
|
119
131
|
|
120
132
|
#
|
121
133
|
# concatenate numbers given in words as bit patterns
|
134
|
+
# (the opposite of split_to_words)
|
122
135
|
#
|
123
136
|
def LongMath.merge_from_words(words, word_len = 32)
|
124
137
|
check_word_len(word_len)
|
@@ -139,7 +152,10 @@ module LongMath
|
|
139
152
|
end
|
140
153
|
|
141
154
|
#
|
142
|
-
|
155
|
+
|
156
|
+
# calculate the square root of an integer x using bitwise algorithm
|
157
|
+
# the result is rounded to an integer y such that
|
158
|
+
# y**2�<=�x�<�(y+1)**2
|
143
159
|
#
|
144
160
|
def LongMath.sqrtb(x)
|
145
161
|
a = sqrtb_with_remainder(x)
|
@@ -147,13 +163,13 @@ module LongMath
|
|
147
163
|
end
|
148
164
|
|
149
165
|
#
|
150
|
-
|
151
|
-
|
166
|
+
#�calculate�the�an�integer�s�>=�0�and�a�remainder�r�>=�0�such�that
|
167
|
+
#�x�=�s**2�+�r�and�s**2�<=�x�<�(s+1)**2
|
152
168
|
# the bitwise algorithm is used, which works well for relatively
|
153
169
|
# small values of x.
|
154
170
|
#
|
155
171
|
def LongMath.sqrtb_with_remainder(x)
|
156
|
-
check_is_int(x)
|
172
|
+
check_is_int(x, "x")
|
157
173
|
|
158
174
|
s = (x <=> 0)
|
159
175
|
if (s == 0) then
|
@@ -182,7 +198,14 @@ module LongMath
|
|
182
198
|
end
|
183
199
|
|
184
200
|
#
|
185
|
-
|
201
|
+
|
202
|
+
# calculate the square root of an integer using larger chunks of the
|
203
|
+
# number. The optional parameter n provides the size of these
|
204
|
+
# chunks. It is by default chosen to be 16, which is optimized for
|
205
|
+
# 32 bit systems, because internally parts of the double size are
|
206
|
+
# used.
|
207
|
+
# the result is rounded to an integer y such that
|
208
|
+
# y**2�<=�x�<�(y+1)**2
|
186
209
|
#
|
187
210
|
def LongMath.sqrtw(x, n = 16)
|
188
211
|
a = sqrtw_with_remainder(x, n)
|
@@ -191,14 +214,14 @@ module LongMath
|
|
191
214
|
|
192
215
|
#
|
193
216
|
# calculate the an integer s >= 0 and a remainder r >= 0 such that
|
194
|
-
|
217
|
+
#�x�=�s**2�+�r�and�s**2�<=�x�<�(s+1)**2
|
195
218
|
# the wordwise algorithm is used, which works well for relatively
|
196
219
|
# large values of x. n defines the word size to be used for the
|
197
220
|
# algorithm. It is good to use half of the machine word, but the
|
198
221
|
# algorithm would also work for other values.
|
199
222
|
#
|
200
223
|
def LongMath.sqrtw_with_remainder(x, n = 16)
|
201
|
-
check_is_int(x)
|
224
|
+
check_is_int(x, "x")
|
202
225
|
check_is_int(n, "n")
|
203
226
|
n2 = n<<1
|
204
227
|
n1 = n+1
|
@@ -257,9 +280,10 @@ module LongMath
|
|
257
280
|
end
|
258
281
|
|
259
282
|
#
|
260
|
-
|
261
|
-
#
|
262
|
-
#
|
283
|
+
|
284
|
+
# find the gcd of an Integer x with b**n0 where n0 is a sufficiently
|
285
|
+
# high exponent
|
286
|
+
# such that gcd(x, b**m) = gcd(x, b**n) for all m, n >= n0
|
263
287
|
#
|
264
288
|
def LongMath.gcd_with_high_power(x, b)
|
265
289
|
check_is_int(x, "x")
|
@@ -283,9 +307,12 @@ module LongMath
|
|
283
307
|
end
|
284
308
|
|
285
309
|
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
310
|
+
# Find the exponent of the highest power of prime number p that divides
|
311
|
+
# the Integer x. Only works for prime numbers p (parameter prime_number).
|
312
|
+
# The caller has to make sure that p (parameter prime_number) is
|
313
|
+
# actually a prime number, because checks for primality actually cost
|
314
|
+
# something and should not be duplicated more than necessary.
|
315
|
+
# This method works even for numbers x that exceed the range of Float
|
289
316
|
#
|
290
317
|
def LongMath.multiplicity_of_factor(x, prime_number)
|
291
318
|
|
@@ -325,12 +352,14 @@ module LongMath
|
|
325
352
|
|
326
353
|
#
|
327
354
|
# method for calculating pi to the given number of digits after the
|
328
|
-
# decimal point
|
329
|
-
# works fine for 1000 or 2000 digits or so.
|
330
|
-
#
|
355
|
+
# decimal point.
|
356
|
+
# It works fine for 1000 or 2000 digits or so.
|
357
|
+
# This method could be optimized more, but if you really want to go
|
331
358
|
# for more digits, you will find a specialized and optimized program
|
332
|
-
# for this specific purpose
|
333
|
-
#
|
359
|
+
# for this specific purpose, probably written in C or C++.
|
360
|
+
# Since calculation of pi is not what should typically be done with
|
361
|
+
# LongDecimal, you may consider this method to be the easter egg of
|
362
|
+
# LongDecimal. ;-)
|
334
363
|
#
|
335
364
|
def LongMath.calc_pi(prec, final_mode = LongDecimal::ROUND_HALF_DOWN)
|
336
365
|
mode = LongDecimal::ROUND_HALF_DOWN
|
@@ -368,7 +397,10 @@ module LongMath
|
|
368
397
|
#
|
369
398
|
# calc the exponential function of x to the given precision as
|
370
399
|
# LongDecimal. Only supports values of x such that the result still
|
371
|
-
# fits into a float (x <= 709)
|
400
|
+
# fits into a float (x <= 709). This limitation is somewhat
|
401
|
+
# arbitrary, but it is enforced in order to avoid producing numbers
|
402
|
+
# with the exponential function that exceed the memory. It may be
|
403
|
+
# removed in future versions.
|
372
404
|
#
|
373
405
|
def LongMath.exp(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
374
406
|
check_is_ld(x, "x")
|
@@ -495,7 +527,7 @@ module LongMath
|
|
495
527
|
end
|
496
528
|
|
497
529
|
#
|
498
|
-
#
|
530
|
+
# calculate the natural logarithm function of x to the given precision as
|
499
531
|
# LongDecimal.
|
500
532
|
#
|
501
533
|
def LongMath.log(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
@@ -506,7 +538,7 @@ module LongMath
|
|
506
538
|
end
|
507
539
|
|
508
540
|
#
|
509
|
-
#
|
541
|
+
# calculate the base 10 logarithm of x to the given precision as
|
510
542
|
# LongDecimal.
|
511
543
|
#
|
512
544
|
def LongMath.log10(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
@@ -526,7 +558,7 @@ module LongMath
|
|
526
558
|
end
|
527
559
|
|
528
560
|
#
|
529
|
-
#
|
561
|
+
# calculate the base 2 logarithm of x to the given precision as
|
530
562
|
# LongDecimal.
|
531
563
|
#
|
532
564
|
def LongMath.log2(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
@@ -659,7 +691,7 @@ end # LongMath
|
|
659
691
|
# digits and the other one the position of the decimal point.
|
660
692
|
#
|
661
693
|
class LongDecimal < Numeric
|
662
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
694
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.8 2006/03/14 20:25:22 bk1 Exp $-'
|
663
695
|
|
664
696
|
include LongDecimalRoundingMode
|
665
697
|
|
@@ -676,6 +708,7 @@ class LongDecimal < Numeric
|
|
676
708
|
# the resulting LongDecimal holds the number x, possibly rounded
|
677
709
|
# 2. LongDecimal.new!(x, s) where x is a string or a number and s is the scale
|
678
710
|
# the resulting LongDecimal holds the number x / 10**s
|
711
|
+
#
|
679
712
|
def LongDecimal.new!(x, s = 0)
|
680
713
|
new(x, s)
|
681
714
|
end
|
@@ -731,7 +764,7 @@ class LongDecimal < Numeric
|
|
731
764
|
# point (scale=s)
|
732
765
|
#
|
733
766
|
def LongDecimal.power_of_ten!(e, s = 0)
|
734
|
-
|
767
|
+
LongMath.check_is_int(e, "e")
|
735
768
|
raise TypeError, "negative 1st arg \"#{e.inspect}\"" if e < 0
|
736
769
|
new(10**(s+e), s)
|
737
770
|
end
|
@@ -838,26 +871,28 @@ class LongDecimal < Numeric
|
|
838
871
|
|
839
872
|
end # initialize
|
840
873
|
|
841
|
-
|
842
|
-
# get the integer value of self, disregarding the decimal point.
|
843
|
-
# Mostly for internal use.
|
844
|
-
#
|
845
|
-
def int_val
|
846
|
-
@int_val
|
847
|
-
end
|
874
|
+
attr_reader :int_val, :scale
|
848
875
|
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
876
|
+
# #
|
877
|
+
# # get the integer value of self, disregarding the decimal point.
|
878
|
+
# # Mostly for internal use.
|
879
|
+
# #
|
880
|
+
# def int_val
|
881
|
+
# @int_val
|
882
|
+
# end
|
856
883
|
|
884
|
+
# #
|
885
|
+
# # get the scale, i.e. the position of the decimal point.
|
886
|
+
# # Mostly for internal use.
|
887
|
+
# #
|
888
|
+
# def scale
|
889
|
+
# @scale
|
890
|
+
# end
|
891
|
+
|
892
|
+
#
|
893
|
+
# alter scale (changes self)
|
857
894
|
#
|
858
|
-
#
|
859
|
-
# only for internal use.
|
860
|
-
# changes self
|
895
|
+
# only for internal use:
|
861
896
|
# use round_to_scale instead
|
862
897
|
#
|
863
898
|
def scale=(s)
|
@@ -885,7 +920,10 @@ class LongDecimal < Numeric
|
|
885
920
|
#
|
886
921
|
# create copy of self with different scale
|
887
922
|
# param1: new_scale new scale for result
|
888
|
-
# param2: mode rounding mode to be applied when information is
|
923
|
+
# param2: mode rounding mode to be applied when information is
|
924
|
+
# lost. defaults to ROUND_UNNECESSARY, which
|
925
|
+
# means that an exception is thrown if rounding
|
926
|
+
# would actually loose any information.
|
889
927
|
#
|
890
928
|
def round_to_scale(new_scale, mode = ROUND_UNNECESSARY)
|
891
929
|
|
@@ -917,6 +955,14 @@ class LongDecimal < Numeric
|
|
917
955
|
#
|
918
956
|
# convert self into String, which is the decimal representation.
|
919
957
|
# Use trailing zeros, if int_val has them.
|
958
|
+
|
959
|
+
# optional parameter shown_scale is the number of digits after the
|
960
|
+
# decimal point. Defaults to the scale of self.
|
961
|
+
# optional parameter mode ist the rounding mode to be applied.
|
962
|
+
# Defaults to ROUND_UNNECESSARY, in which case an exception is
|
963
|
+
# thrown if rounding is actually necessary.
|
964
|
+
# optional parameter base is the base to be used when expressing
|
965
|
+
# self as string. defaults to 10.
|
920
966
|
#
|
921
967
|
def to_s(shown_scale = @scale, mode = ROUND_UNNECESSARY, base = 10)
|
922
968
|
if (base == 10) then
|
@@ -939,10 +985,17 @@ class LongDecimal < Numeric
|
|
939
985
|
end
|
940
986
|
end
|
941
987
|
|
988
|
+
#
|
989
|
+
# internal helper method, converts self to string in decimal system
|
990
|
+
# with default settings.
|
991
|
+
#
|
942
992
|
def to_s_10
|
943
993
|
to_s_internal(10, scale)
|
944
994
|
end
|
945
995
|
|
996
|
+
#
|
997
|
+
# internal helper method, converts self to string in any number system
|
998
|
+
#
|
946
999
|
def to_s_internal(b, sc)
|
947
1000
|
sg = sgn
|
948
1001
|
i = int_val.abs
|
@@ -973,7 +1026,9 @@ class LongDecimal < Numeric
|
|
973
1026
|
#
|
974
1027
|
# convert self into Float
|
975
1028
|
# this works straitforward by dividing int_val by power of 10 in
|
976
|
-
# float-arithmetic
|
1029
|
+
# float-arithmetic, in all cases where numerator and denominator are
|
1030
|
+
# within the ranges expressable as Floats. Goes via string
|
1031
|
+
# representation otherwise.
|
977
1032
|
#
|
978
1033
|
def to_f
|
979
1034
|
divisor = denominator
|
@@ -983,16 +1038,11 @@ class LongDecimal < Numeric
|
|
983
1038
|
if (divisor.abs > LongMath::MAX_FLOATABLE) then
|
984
1039
|
return 0.0
|
985
1040
|
else
|
986
|
-
# puts("int_val=#{int_val}")
|
987
|
-
# $defout.flush
|
988
1041
|
f = int_val.to_f
|
989
|
-
|
990
|
-
# $defout.flush
|
991
|
-
return f / divisor
|
992
|
-
# int_val.to_f / 10**scale
|
1042
|
+
return f / divisor
|
993
1043
|
end
|
994
1044
|
elsif numerator.abs < divisor
|
995
|
-
#
|
1045
|
+
# self is between -1 and 1
|
996
1046
|
# factor = numerator.abs.div(LongMath::MAX_FLOATABLE)
|
997
1047
|
# digits = factor.to_ld.int_digits10
|
998
1048
|
# return LongDecimal(numerator.div(10**digits), scale -digits).to_f
|
@@ -1011,7 +1061,7 @@ class LongDecimal < Numeric
|
|
1011
1061
|
# to_i when the number represented by self is actually an integer.
|
1012
1062
|
#
|
1013
1063
|
def to_i
|
1014
|
-
(
|
1064
|
+
numerator.div(denominator)
|
1015
1065
|
end
|
1016
1066
|
|
1017
1067
|
#
|
@@ -1033,7 +1083,10 @@ class LongDecimal < Numeric
|
|
1033
1083
|
#
|
1034
1084
|
# LongDecimals can be seen as a fraction with a power of 10 as
|
1035
1085
|
# denominator for compatibility with other numeric classes this
|
1036
|
-
# method is included, returning 10**scale
|
1086
|
+
# method is included, returning 10**scale.
|
1087
|
+
# Please observe that there may be common factors of numerator and
|
1088
|
+
# denominator in case of LongDecimal, which does not occur in case
|
1089
|
+
# of Rational
|
1037
1090
|
#
|
1038
1091
|
def denominator
|
1039
1092
|
10**scale
|
@@ -1042,11 +1095,20 @@ class LongDecimal < Numeric
|
|
1042
1095
|
#
|
1043
1096
|
# LongDecimals can be seen as a fraction with its int_val as its
|
1044
1097
|
# numerator
|
1098
|
+
# Please observe that there may be common factors of numerator and
|
1099
|
+
# denominator in case of LongDecimal, which does not occur in case
|
1100
|
+
# of Rational
|
1045
1101
|
#
|
1046
1102
|
alias numerator int_val
|
1047
1103
|
|
1048
1104
|
#
|
1049
1105
|
# number of binary digits before the decimal point, not counting a single 0.
|
1106
|
+
# 0.xxx -> 0
|
1107
|
+
# 1.xxx -> 1
|
1108
|
+
# 2.xxx -> 2
|
1109
|
+
# 4.xxx -> 3
|
1110
|
+
# 8.xxx -> 4
|
1111
|
+
# ...
|
1050
1112
|
#
|
1051
1113
|
def int_digits2
|
1052
1114
|
int_part = self.to_i.abs
|
@@ -1064,7 +1126,12 @@ class LongDecimal < Numeric
|
|
1064
1126
|
end
|
1065
1127
|
|
1066
1128
|
#
|
1067
|
-
# number of decimal digits before the decimal point, not counting a
|
1129
|
+
# number of decimal digits before the decimal point, not counting a
|
1130
|
+
# single 0.
|
1131
|
+
# 0.xxx -> 0
|
1132
|
+
# 1.xxx -> 1
|
1133
|
+
# 10.xxx -> 2
|
1134
|
+
# ...
|
1068
1135
|
#
|
1069
1136
|
def int_digits10
|
1070
1137
|
int_part = self.to_i.abs
|
@@ -1139,7 +1206,9 @@ class LongDecimal < Numeric
|
|
1139
1206
|
end
|
1140
1207
|
|
1141
1208
|
#
|
1142
|
-
# successor for ranges
|
1209
|
+
# successor as needed for using LongDecimal in ranges
|
1210
|
+
# it needs to be observed that this is usually not an increment by
|
1211
|
+
# 1, but by 1/10**scale.
|
1143
1212
|
#
|
1144
1213
|
def succ
|
1145
1214
|
LongDecimal(int_val + 1, scale)
|
@@ -1148,7 +1217,9 @@ class LongDecimal < Numeric
|
|
1148
1217
|
alias next succ
|
1149
1218
|
|
1150
1219
|
#
|
1151
|
-
# predecessor
|
1220
|
+
# predecessor (opposite of successor)
|
1221
|
+
# it needs to be observed that this is usually not an decrement by
|
1222
|
+
# 1, but by 1/10**scale.
|
1152
1223
|
#
|
1153
1224
|
def pred
|
1154
1225
|
LongDecimal(int_val - 1, scale)
|
@@ -1168,6 +1239,20 @@ class LongDecimal < Numeric
|
|
1168
1239
|
self - 1
|
1169
1240
|
end
|
1170
1241
|
|
1242
|
+
#
|
1243
|
+
# self += 1
|
1244
|
+
#
|
1245
|
+
def inc!
|
1246
|
+
@int_val += denominator
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
#
|
1250
|
+
# self -= 1
|
1251
|
+
#
|
1252
|
+
def dec!
|
1253
|
+
@int_val -= denominator
|
1254
|
+
end
|
1255
|
+
|
1171
1256
|
#
|
1172
1257
|
# return the unit by which self is incremented by succ
|
1173
1258
|
#
|
@@ -1286,6 +1371,16 @@ class LongDecimal < Numeric
|
|
1286
1371
|
end
|
1287
1372
|
end
|
1288
1373
|
|
1374
|
+
#
|
1375
|
+
# divide self by other and return result as LongDecimalQuot
|
1376
|
+
# because division does not have an obvious rounding rule like
|
1377
|
+
# addition, subtraction and multiplication, the result needs to be
|
1378
|
+
# rounded afterwards to become a LongDecimal again. This way
|
1379
|
+
# calculations can still be done in the natural readable way using +,
|
1380
|
+
# -, *, and /, but the rounding can be provided later.
|
1381
|
+
# It is very important in complicated calculations put the rounding
|
1382
|
+
# steps in the right places, usually after having performed a division.
|
1383
|
+
#
|
1289
1384
|
def /(other)
|
1290
1385
|
o, s = coerce(other)
|
1291
1386
|
if (s.kind_of? LongDecimal) then
|
@@ -1295,6 +1390,17 @@ class LongDecimal < Numeric
|
|
1295
1390
|
end
|
1296
1391
|
end
|
1297
1392
|
|
1393
|
+
#
|
1394
|
+
# power of self (LongDecimal) with other.
|
1395
|
+
# if other is expressable as non-negative integer, the power is what
|
1396
|
+
# would be obtained by successive multiplications.
|
1397
|
+
# if other is expressable as negative integer, the power is a
|
1398
|
+
# LongDecimalQuot as would result by successive division, but with
|
1399
|
+
# the same scale as the positive power would get. Explicit rounding
|
1400
|
+
# is needed to convert into a LongDecimal again
|
1401
|
+
# in all other cases, self is converted into a Rational prior to
|
1402
|
+
# applying power, usually resulting in a Float as power.
|
1403
|
+
#
|
1298
1404
|
def **(other)
|
1299
1405
|
if ((other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)) && other.is_int? then
|
1300
1406
|
other = other.to_i
|
@@ -1315,6 +1421,9 @@ class LongDecimal < Numeric
|
|
1315
1421
|
end
|
1316
1422
|
end
|
1317
1423
|
|
1424
|
+
#
|
1425
|
+
# do integer division with remainder, returning two values
|
1426
|
+
#
|
1318
1427
|
def divmod(other)
|
1319
1428
|
if (other.kind_of? Complex) then
|
1320
1429
|
raise TypeError, "divmod not supported for Complex"
|
@@ -1323,13 +1432,16 @@ class LongDecimal < Numeric
|
|
1323
1432
|
return q, self - other * q
|
1324
1433
|
end
|
1325
1434
|
|
1435
|
+
#
|
1436
|
+
# remainder of integer division by other
|
1437
|
+
#
|
1326
1438
|
def %(other)
|
1327
1439
|
q, r = divmod other
|
1328
1440
|
r
|
1329
1441
|
end
|
1330
1442
|
|
1331
1443
|
#
|
1332
|
-
# performs bitwise AND between self and
|
1444
|
+
# performs bitwise AND between self and other
|
1333
1445
|
#
|
1334
1446
|
def &(other)
|
1335
1447
|
s, o = equalize_scale(other)
|
@@ -1341,7 +1453,7 @@ class LongDecimal < Numeric
|
|
1341
1453
|
end
|
1342
1454
|
|
1343
1455
|
#
|
1344
|
-
# performs bitwise OR between self and
|
1456
|
+
# performs bitwise OR between self and other
|
1345
1457
|
#
|
1346
1458
|
def |(other)
|
1347
1459
|
s, o = equalize_scale(other)
|
@@ -1353,7 +1465,7 @@ class LongDecimal < Numeric
|
|
1353
1465
|
end
|
1354
1466
|
|
1355
1467
|
#
|
1356
|
-
# performs bitwise XOR between self and
|
1468
|
+
# performs bitwise XOR between self and other
|
1357
1469
|
#
|
1358
1470
|
def ^(other)
|
1359
1471
|
s, o = equalize_scale(other)
|
@@ -1372,7 +1484,7 @@ class LongDecimal < Numeric
|
|
1372
1484
|
end
|
1373
1485
|
|
1374
1486
|
#
|
1375
|
-
# performs bitwise left shift of self by
|
1487
|
+
# performs bitwise left shift of self by other
|
1376
1488
|
#
|
1377
1489
|
def <<(other)
|
1378
1490
|
unless (other.kind_of? Integer) && other >= 0 then
|
@@ -1382,7 +1494,7 @@ class LongDecimal < Numeric
|
|
1382
1494
|
end
|
1383
1495
|
|
1384
1496
|
#
|
1385
|
-
# performs bitwise right shift of self by
|
1497
|
+
# performs bitwise right shift of self by other
|
1386
1498
|
#
|
1387
1499
|
def >>(other)
|
1388
1500
|
unless (other.kind_of? Integer) && other >= 0 then
|
@@ -1392,7 +1504,7 @@ class LongDecimal < Numeric
|
|
1392
1504
|
end
|
1393
1505
|
|
1394
1506
|
#
|
1395
|
-
# gets binary digit
|
1507
|
+
# gets binary digit of self
|
1396
1508
|
#
|
1397
1509
|
def [](other)
|
1398
1510
|
int_val[other]
|
@@ -1430,6 +1542,7 @@ class LongDecimal < Numeric
|
|
1430
1542
|
end
|
1431
1543
|
|
1432
1544
|
#
|
1545
|
+
# internal method
|
1433
1546
|
# divide by 10**n
|
1434
1547
|
#
|
1435
1548
|
def move_point_left_int(n)
|
@@ -1438,6 +1551,7 @@ class LongDecimal < Numeric
|
|
1438
1551
|
end
|
1439
1552
|
|
1440
1553
|
#
|
1554
|
+
# internal method
|
1441
1555
|
# multiply by 10**n
|
1442
1556
|
#
|
1443
1557
|
def move_point_right_int(n)
|
@@ -1482,6 +1596,8 @@ class LongDecimal < Numeric
|
|
1482
1596
|
1 / self
|
1483
1597
|
end
|
1484
1598
|
|
1599
|
+
alias inverse reciprocal
|
1600
|
+
|
1485
1601
|
#
|
1486
1602
|
# Absolute value
|
1487
1603
|
#
|
@@ -1491,13 +1607,22 @@ class LongDecimal < Numeric
|
|
1491
1607
|
|
1492
1608
|
#
|
1493
1609
|
# square of absolute value
|
1610
|
+
# happens to be the square
|
1494
1611
|
#
|
1495
|
-
|
1496
|
-
self.abs.square
|
1497
|
-
end
|
1612
|
+
alias abs2 square
|
1498
1613
|
|
1499
1614
|
#
|
1500
|
-
# Compares the
|
1615
|
+
# Compares the two numbers.
|
1616
|
+
# returns -1 if self < other
|
1617
|
+
# 0 if self-other = 0
|
1618
|
+
# +1 if self > other
|
1619
|
+
# it needs to be observed, that
|
1620
|
+
# x == y implies (x <=> y) == 0
|
1621
|
+
# but not
|
1622
|
+
# (x <=> y) == 0 implies x == y
|
1623
|
+
# because == also takes the scale into account and considers two
|
1624
|
+
# numbers only equal, if they have the same number of potentially
|
1625
|
+
# zero digits after the decimal point.
|
1501
1626
|
#
|
1502
1627
|
def <=> (other)
|
1503
1628
|
diff = (self - other)
|
@@ -1508,15 +1633,26 @@ class LongDecimal < Numeric
|
|
1508
1633
|
end
|
1509
1634
|
end
|
1510
1635
|
|
1636
|
+
#
|
1637
|
+
# <=>-comparison for the scales
|
1638
|
+
#
|
1511
1639
|
def scale_ufo(other)
|
1512
1640
|
raise TypeError, "only works for LongDecimal and LongDecimalQuot" unless (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)
|
1513
1641
|
self.scale <=> other.scale
|
1514
1642
|
end
|
1515
1643
|
|
1644
|
+
#
|
1645
|
+
# ==-comparison for the scales
|
1646
|
+
#
|
1516
1647
|
def scale_equal(other)
|
1517
1648
|
scale_ufo(other).zero?
|
1518
1649
|
end
|
1519
1650
|
|
1651
|
+
#
|
1652
|
+
# return a pair o, s resembling other, self, but potentially
|
1653
|
+
# converted to compatible types and ready for
|
1654
|
+
# arithmetic operations.
|
1655
|
+
#
|
1520
1656
|
def coerce(other)
|
1521
1657
|
if other.kind_of? LongDecimal then
|
1522
1658
|
return other, self
|
@@ -1550,25 +1686,48 @@ class LongDecimal < Numeric
|
|
1550
1686
|
end
|
1551
1687
|
end
|
1552
1688
|
|
1689
|
+
#
|
1553
1690
|
# is self expressable as an integer without loss of digits?
|
1691
|
+
#
|
1554
1692
|
def is_int?
|
1555
1693
|
scale == 0 || int_val % 10**scale == 0
|
1556
1694
|
end
|
1557
1695
|
|
1696
|
+
#
|
1697
|
+
# get the sign of self
|
1698
|
+
# -1 if self < 0
|
1699
|
+
# 0 if self is 0 (with any number of 0s after the decimal point)
|
1700
|
+
# +1 if self > 0
|
1701
|
+
#
|
1558
1702
|
def sgn
|
1559
1703
|
int_val <=> 0
|
1560
1704
|
end
|
1705
|
+
|
1561
1706
|
alias signum sgn
|
1562
1707
|
alias sign sgn
|
1563
1708
|
|
1709
|
+
#
|
1710
|
+
# comparison of self with other for equality
|
1711
|
+
# takes into account the values expressed by self and other and the
|
1712
|
+
# equality of the number of digits.
|
1713
|
+
#
|
1564
1714
|
def ==(other)
|
1565
|
-
(other.kind_of? LongDecimal) && (self <=> other) == 0 && self.scale == other.scale
|
1715
|
+
# (other.kind_of? LongDecimal) && (self <=> other) == 0 && self.scale == other.scale
|
1716
|
+
(other.kind_of? LongDecimal) && self.int_val == other.int_val && self.scale == other.scale
|
1566
1717
|
end
|
1567
1718
|
|
1719
|
+
#
|
1720
|
+
# check if the number expressed by self is 0 (zero)
|
1721
|
+
# with any number of 0s after the decimal point.
|
1722
|
+
#
|
1568
1723
|
def zero?
|
1569
1724
|
int_val.zero?
|
1570
1725
|
end
|
1571
1726
|
|
1727
|
+
#
|
1728
|
+
# check if the number expressed by self is 1 (one)
|
1729
|
+
# with any number of 0s after the decimal point.
|
1730
|
+
#
|
1572
1731
|
def one?
|
1573
1732
|
(self-1).zero?
|
1574
1733
|
end
|
@@ -1596,10 +1755,19 @@ end # LongDecimal
|
|
1596
1755
|
#
|
1597
1756
|
class LongDecimalQuot < Numeric
|
1598
1757
|
|
1599
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
1758
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.8 2006/03/14 20:25:22 bk1 Exp $-'
|
1600
1759
|
|
1601
1760
|
include LongDecimalRoundingMode
|
1602
1761
|
|
1762
|
+
#
|
1763
|
+
# constructor
|
1764
|
+
# first, second is either a pair of LongDecimals or a Rational and an Integer
|
1765
|
+
# The resulting LongDecimal will contain a rational obtained by
|
1766
|
+
# dividing the two LongDecimals or by taking the Rational as it is.
|
1767
|
+
# The scale is there to provide a default rounding precision for
|
1768
|
+
# conversion to LongDecimal, but it has no influence on the value
|
1769
|
+
# expressed by the LongDecimalQuot
|
1770
|
+
#
|
1603
1771
|
def LongDecimalQuot.new!(first, second)
|
1604
1772
|
new(first, second)
|
1605
1773
|
end
|
@@ -1607,6 +1775,7 @@ class LongDecimalQuot < Numeric
|
|
1607
1775
|
#
|
1608
1776
|
# create a new LongDecimalQuot from a rational and a scale or a
|
1609
1777
|
# pair of LongDecimals
|
1778
|
+
#
|
1610
1779
|
def initialize(first, second)
|
1611
1780
|
if ((first.kind_of? Rational) || (first.kind_of? Integer)) && (second.kind_of? Integer) then
|
1612
1781
|
@rat = Rational(first.numerator, first.denominator)
|
@@ -1621,24 +1790,35 @@ class LongDecimalQuot < Numeric
|
|
1621
1790
|
end
|
1622
1791
|
end
|
1623
1792
|
|
1793
|
+
attr_reader :scale, :rat
|
1624
1794
|
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1795
|
+
# def scale
|
1796
|
+
# @scale
|
1797
|
+
# end
|
1628
1798
|
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1799
|
+
# def rat
|
1800
|
+
# @rat
|
1801
|
+
# end
|
1632
1802
|
|
1803
|
+
#
|
1804
|
+
# numerator of the included rational number.
|
1805
|
+
# LongDecimals should duck type like Rationals
|
1806
|
+
#
|
1633
1807
|
def numerator
|
1634
1808
|
rat.numerator
|
1635
1809
|
end
|
1636
1810
|
|
1811
|
+
#
|
1812
|
+
# denominator of the included rational number.
|
1813
|
+
# LongDecimals should duck type like Rationals
|
1814
|
+
#
|
1637
1815
|
def denominator
|
1638
1816
|
rat.denominator
|
1639
1817
|
end
|
1640
1818
|
|
1641
|
-
#
|
1819
|
+
#
|
1820
|
+
# alter scale (only for internal use)
|
1821
|
+
#
|
1642
1822
|
def scale=(s)
|
1643
1823
|
raise TypeError, "non integer arg \"#{s.inspect}\"" if ! s.kind_of? Integer
|
1644
1824
|
raise TypeError, "negative arg \"#{s.inspect}\"" if s < 0
|
@@ -1647,33 +1827,53 @@ class LongDecimalQuot < Numeric
|
|
1647
1827
|
|
1648
1828
|
private :scale=
|
1649
1829
|
|
1830
|
+
#
|
1831
|
+
# conversion to string. Based on the conversion of Rational
|
1832
|
+
#
|
1650
1833
|
def to_s
|
1651
1834
|
str = @rat.to_s
|
1652
1835
|
str + "[" + scale.to_s + "]"
|
1653
1836
|
end
|
1654
1837
|
|
1838
|
+
#
|
1839
|
+
# conversion to rational
|
1840
|
+
#
|
1655
1841
|
def to_r
|
1656
1842
|
Rational(numerator, denominator)
|
1657
1843
|
end
|
1658
1844
|
|
1845
|
+
#
|
1659
1846
|
# convert into Float
|
1847
|
+
#
|
1660
1848
|
def to_f
|
1661
1849
|
to_r.to_f
|
1662
1850
|
end
|
1663
1851
|
|
1852
|
+
#
|
1664
1853
|
# convert into Integer
|
1854
|
+
#
|
1665
1855
|
def to_i
|
1666
1856
|
to_r.to_i
|
1667
1857
|
end
|
1668
1858
|
|
1859
|
+
#
|
1860
|
+
# conversion to LongDecimal using the internal scale
|
1861
|
+
#
|
1669
1862
|
def to_ld
|
1670
1863
|
round_to_scale(scale, ROUND_HALF_UP)
|
1671
1864
|
end
|
1672
1865
|
|
1866
|
+
#
|
1867
|
+
# unary plus returns self
|
1868
|
+
#
|
1673
1869
|
def +@
|
1674
1870
|
self
|
1675
1871
|
end
|
1676
1872
|
|
1873
|
+
#
|
1874
|
+
# unary minus returns negation of self
|
1875
|
+
# leaves self unchanged.
|
1876
|
+
#
|
1677
1877
|
def -@
|
1678
1878
|
if self.zero? then
|
1679
1879
|
self
|
@@ -1682,6 +1882,12 @@ class LongDecimalQuot < Numeric
|
|
1682
1882
|
end
|
1683
1883
|
end
|
1684
1884
|
|
1885
|
+
#
|
1886
|
+
# addition
|
1887
|
+
# if other can be converted into LongDecimalQuot, add as
|
1888
|
+
# LongDecimalQuot, using the addition of Rationals
|
1889
|
+
# otherwise use BigDecimal, Complex or Float
|
1890
|
+
#
|
1685
1891
|
def +(other)
|
1686
1892
|
o, s = coerce(other)
|
1687
1893
|
if (s.kind_of? LongDecimalQuot) then
|
@@ -1850,6 +2056,15 @@ class LongDecimalQuot < Numeric
|
|
1850
2056
|
LongDecimal(new_int_val, new_scale)
|
1851
2057
|
end
|
1852
2058
|
|
2059
|
+
#
|
2060
|
+
# prepare binary operation of other with LongDecimalQuot
|
2061
|
+
# Integer, LongDecimal, Rational and LongDecimalQuot can be
|
2062
|
+
# expressed as LongDecimalQuot, using the scale of self in case of
|
2063
|
+
# Integer and Rational. Floats can be approximated by LongDecimals
|
2064
|
+
# and thus be expressed as LongDecimalQuot
|
2065
|
+
# In case of BigDecimal, Complex or any unknown type, convert self
|
2066
|
+
# to BigDecimal or Float.
|
2067
|
+
#
|
1853
2068
|
def coerce(other)
|
1854
2069
|
if other.kind_of? LongDecimal then
|
1855
2070
|
return LongDecimalQuot(other.to_r, other.scale), self
|
@@ -1872,12 +2087,22 @@ class LongDecimalQuot < Numeric
|
|
1872
2087
|
end
|
1873
2088
|
end
|
1874
2089
|
|
2090
|
+
#
|
2091
|
+
# compare two numbers for equality.
|
2092
|
+
# The LongDecimalQuot self is considered == to other if and only if
|
2093
|
+
# other is also LongDecimalQuot, expresses the same value and has the
|
2094
|
+
# same scale.
|
2095
|
+
# It needs to be observed that scale does not influence the value expressed
|
2096
|
+
# by the number, but only how rouding is performed by default if no
|
2097
|
+
# explicit number of digits after the decimal point is given. But
|
2098
|
+
# scale needs to match for equality.
|
2099
|
+
#
|
1875
2100
|
def ==(other)
|
1876
2101
|
(other.kind_of? LongDecimalQuot) && (self <=> other) == 0 && self.scale == other.scale
|
1877
2102
|
end
|
1878
2103
|
|
1879
2104
|
#
|
1880
|
-
# Compares the two numbers.
|
2105
|
+
# Compares the two numbers for < and > etc.
|
1881
2106
|
#
|
1882
2107
|
def <=> (other)
|
1883
2108
|
diff = (self - other)
|
@@ -1888,20 +2113,31 @@ class LongDecimalQuot < Numeric
|
|
1888
2113
|
end
|
1889
2114
|
end
|
1890
2115
|
|
2116
|
+
#
|
2117
|
+
# compare scales with <=>
|
2118
|
+
#
|
1891
2119
|
def scale_ufo(other)
|
1892
2120
|
raise TypeError, "only works for LongDecimal and LongDecimalQuot" unless (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)
|
1893
2121
|
self.scale <=> other.scale
|
1894
2122
|
end
|
1895
2123
|
|
2124
|
+
#
|
2125
|
+
# check if scales are equal
|
2126
|
+
#
|
1896
2127
|
def scale_equal(other)
|
1897
2128
|
scale_ufo(other).zero?
|
1898
2129
|
end
|
1899
2130
|
|
2131
|
+
#
|
1900
2132
|
# is self expressable as an integer without loss of digits?
|
2133
|
+
#
|
1901
2134
|
def is_int?
|
1902
2135
|
denominator == 1
|
1903
2136
|
end
|
1904
2137
|
|
2138
|
+
#
|
2139
|
+
# sign of self
|
2140
|
+
#
|
1905
2141
|
def sgn
|
1906
2142
|
numerator <=> 0
|
1907
2143
|
end
|
@@ -1916,11 +2152,6 @@ class LongDecimalQuot < Numeric
|
|
1916
2152
|
end
|
1917
2153
|
|
1918
2154
|
|
1919
|
-
def scale
|
1920
|
-
@scale
|
1921
|
-
end
|
1922
|
-
|
1923
|
-
|
1924
2155
|
#
|
1925
2156
|
# Returns "<tt>LongDecimalQuot(<i>int_val</i>, <i>scale</i>, <i>num</i>, <i>denom</i>)</tt>".
|
1926
2157
|
#
|
@@ -1941,12 +2172,21 @@ def LongDecimal(a, b = 0)
|
|
1941
2172
|
end
|
1942
2173
|
end
|
1943
2174
|
|
2175
|
+
#
|
2176
|
+
# construct a LongDecimalQuot from the given parameters
|
2177
|
+
# 1st case: both are LongDecimals
|
2178
|
+
# 2nd case: first is Rational, second is scale
|
2179
|
+
#
|
1944
2180
|
def LongDecimalQuot(first, second)
|
1945
2181
|
LongDecimalQuot.new!(first, second)
|
1946
2182
|
end
|
1947
2183
|
|
2184
|
+
|
1948
2185
|
class Numeric
|
1949
2186
|
|
2187
|
+
#
|
2188
|
+
# convert self to LongDecimal
|
2189
|
+
#
|
1950
2190
|
def to_ld
|
1951
2191
|
LongDecimal(self)
|
1952
2192
|
end
|