long-decimal 0.00.10 → 0.00.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|