long-decimal 0.00.07 → 0.00.08

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@
2
2
  # Rakefile for long-decimal project
3
3
  #
4
4
  # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/Rakefile,v 1.1 2006/02/25 19:52:11 bk1 Exp $
5
- # CVS-Label: $Name: PRE_ALPHA_0_06 $
5
+ # CVS-Label: $Name: PRE_ALPHA_0_08 $
6
6
  # Author: $Author: bk1 $ (Karl Brodowsky)
7
7
  #
8
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.00.07
1
+ 0.00.08
data/lib/longdecimal.rb CHANGED
@@ -1,13 +1,14 @@
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.3 2006/02/28 09:57:10 bk1 Exp $
5
- # CVS-Label: $Name: PRE_ALPHA_0_07 $
4
+ # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.4 2006/03/02 20:20:12 bk1 Exp $
5
+ # CVS-Label: $Name: PRE_ALPHA_0_08 $
6
6
  # Author: $Author: bk1 $ (Karl Brodowsky)
7
7
  #
8
8
  require "complex"
9
9
  require "rational"
10
- # require "bigdecimal"
10
+ require "bigdecimal"
11
+
11
12
  # require "bigdecimal/math"
12
13
 
13
14
  #
@@ -216,7 +217,7 @@ module LongMath
216
217
  return m1 - m2
217
218
 
218
219
  elsif (x.kind_of? LongDecimal)
219
- m1 = x.numerator.multiplicity_of_factor(prime_number)
220
+ m1 = multiplicity_of_factor(x.numerator, prime_number)
220
221
  if (prime_number == 2 || prime_number == 5) then
221
222
  return m1 - x.scale
222
223
  else
@@ -244,6 +245,47 @@ module LongMath
244
245
  end
245
246
  end
246
247
 
248
+ #
249
+ # method for calculating pi to the given number of digits after the
250
+ # decimal point
251
+ # works fine for 1000 or 2000 digits or so.
252
+ # this method could be optimized more, but if you really want to go
253
+ # for more digits, you will find a specialized and optimized program
254
+ # for this specific purpose.
255
+ # (this is the easter egg ;-) )
256
+ def LongMath.calc_pi(prec, final_mode = LongDecimal::ROUND_HALF_DOWN)
257
+ mode = LongDecimal::ROUND_HALF_DOWN
258
+ iprec = 5*(prec+1)
259
+ sprec = (iprec >> 1) + 1
260
+ dprec = (prec+1) << 1
261
+
262
+ a = LongDecimal(1)
263
+ b = (1 / LongDecimal(2).sqrt(iprec,mode)).round_to_scale(iprec, mode)
264
+ c = LongDecimal(5,1)
265
+ k = 1
266
+ pow_k = 2
267
+
268
+ pi = 0
269
+ last_pi = 0
270
+ last_diff = 1
271
+
272
+ loop do
273
+ a, b = ((a + b) / 2).round_to_scale(sprec, mode), (a * b).round_to_scale(iprec, mode).sqrt(sprec, mode)
274
+ c = (c - pow_k * (a * a - b * b)).round_to_scale(iprec, mode)
275
+ pi = (2 * a * a / c).round_to_scale(sprec, mode)
276
+ diff = (pi - last_pi).round_to_scale(dprec, mode).abs
277
+ if (diff.zero? && last_diff.zero?) then
278
+ break
279
+ end
280
+ last_pi = pi
281
+ last_diff = diff
282
+ k += 1
283
+ pow_k = pow_k << 1
284
+ # puts("k=#{k} pi=#{pi.to_s}\nd=#{diff}\n\n")
285
+ end
286
+ pi.round_to_scale(prec, final_mode)
287
+ end
288
+
247
289
  end
248
290
 
249
291
  #
@@ -286,7 +328,7 @@ end
286
328
  # digits and the other one the position of the decimal point.
287
329
  #
288
330
  class LongDecimal < Numeric
289
- @RCS_ID='-$Id: longdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
331
+ @RCS_ID='-$Id: longdecimal.rb,v 1.4 2006/03/02 20:20:12 bk1 Exp $-'
290
332
 
291
333
  include LongDecimalRoundingMode
292
334
 
@@ -407,7 +449,10 @@ class LongDecimal < Numeric
407
449
 
408
450
  else
409
451
  # we assume a string or a floating point number
410
- # floating point number is converted to string, so we only deal with strings
452
+ # floating point number or BigDecimal is converted to string, so
453
+ # we only deal with strings
454
+ # this operation is not so common, so there is no urgent need to
455
+ # optimize it
411
456
  num_str = x.to_s
412
457
  len = num_str.length
413
458
 
@@ -618,6 +663,15 @@ class LongDecimal < Numeric
618
663
  self
619
664
  end
620
665
 
666
+ #
667
+ # convert selt into BigDecimal
668
+ #
669
+ def to_bd
670
+ # this operation is probably not used so heavily, so we can live with a
671
+ # string as an intermediate step.
672
+ BigDecimal(self.to_s)
673
+ end
674
+
621
675
  #
622
676
  # LongDecimals can be seen as a fraction with a power of 10 as
623
677
  # denominator for compatibility with other numeric classes this
@@ -1054,6 +1108,11 @@ class LongDecimal < Numeric
1054
1108
  other = other.round_to_scale(scale, ROUND_HALF_UP)
1055
1109
  end
1056
1110
  return other, self
1111
+ elsif other.kind_of? BigDecimal then
1112
+ s, o = other.coerce(self.to_bd)
1113
+ return o, s
1114
+ elsif (other.kind_of? Float) && size > 8 then
1115
+ return coerce(BigDecimal(other.to_s))
1057
1116
  elsif other.kind_of? Numeric then
1058
1117
  s, o = other.coerce(self.to_f)
1059
1118
  return o, s
@@ -1104,7 +1163,7 @@ end
1104
1163
  #
1105
1164
  class LongDecimalQuot < Numeric
1106
1165
 
1107
- @RCS_ID='-$Id: longdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
1166
+ @RCS_ID='-$Id: longdecimal.rb,v 1.4 2006/03/02 20:20:12 bk1 Exp $-'
1108
1167
 
1109
1168
  include LongDecimalRoundingMode
1110
1169
 
@@ -1372,6 +1431,8 @@ class LongDecimalQuot < Numeric
1372
1431
  return LongDecimalQuot(other.to_r, scale), self
1373
1432
  elsif other.kind_of? Float then
1374
1433
  return LongDecimalQuot(other.to_ld.to_r, scale), self
1434
+ elsif other.kind_of? BigDecimal then
1435
+ s, o = other.coerce(self.to_bd)
1375
1436
  elsif other.kind_of? Numeric then
1376
1437
  s, o = other.coerce(self.to_f)
1377
1438
  return o, s
@@ -2,8 +2,8 @@
2
2
  #
3
3
  # testlongdecimal.rb -- runit test for longdecimal.rb
4
4
  #
5
- # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $
6
- # CVS-Label: $Name: PRE_ALPHA_0_07 $
5
+ # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdecimal.rb,v 1.4 2006/03/02 20:20:12 bk1 Exp $
6
+ # CVS-Label: $Name: PRE_ALPHA_0_08 $
7
7
  # Author: $Author: bk1 $ (Karl Brodowsky)
8
8
  #
9
9
 
@@ -13,10 +13,16 @@ require "runit/testsuite"
13
13
 
14
14
  load "lib/longdecimal.rb"
15
15
 
16
+ #
17
+ # test class for LongDecimal and LongDecimalQuot
18
+ #
16
19
  class TestLongDecimal_class < RUNIT::TestCase
17
20
 
18
- @RCS_ID='-$Id: testlongdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
21
+ @RCS_ID='-$Id: testlongdecimal.rb,v 1.4 2006/03/02 20:20:12 bk1 Exp $-'
19
22
 
23
+ #
24
+ # helper method for test_sqrtb
25
+ #
20
26
  def check_sqrtb(x, s)
21
27
  y = LongMath.sqrtb(x)
22
28
  z = y * y
@@ -26,7 +32,10 @@ class TestLongDecimal_class < RUNIT::TestCase
26
32
  y
27
33
  end
28
34
 
29
- def _test_sqrtb
35
+ #
36
+ # test method sqrtb for calculating sqrt of short integers
37
+ #
38
+ def test_sqrtb
30
39
  assert_equal(Complex(0,1), LongMath.sqrtb(-1), "sqrt(-1)=i")
31
40
  1024.times do |x|
32
41
  check_sqrtb(x, " loop x=#{x}")
@@ -61,6 +70,9 @@ class TestLongDecimal_class < RUNIT::TestCase
61
70
  end
62
71
  end
63
72
 
73
+ #
74
+ # helper method of test_sqrtw
75
+ #
64
76
  def check_sqrtw(x, s)
65
77
  y = LongMath.sqrtw(x)
66
78
  z = y * y
@@ -70,6 +82,9 @@ class TestLongDecimal_class < RUNIT::TestCase
70
82
  y
71
83
  end
72
84
 
85
+ #
86
+ # test method sqrtb for calculating sqrt of long integers
87
+ #
73
88
  def test_sqrtw
74
89
  assert_equal(Complex(0,1), LongMath.sqrtw(-1), "sqrt(-1)=i")
75
90
  1024.times do |x|
@@ -105,6 +120,9 @@ class TestLongDecimal_class < RUNIT::TestCase
105
120
  end
106
121
  end
107
122
 
123
+ #
124
+ # test gcd_with_high_power
125
+ #
108
126
  def test_gcd_with_high_power
109
127
  n = 224
110
128
  assert_equal(32, LongMath.gcd_with_high_power(n, 2), "2-part of 224 is 32")
@@ -112,6 +130,9 @@ class TestLongDecimal_class < RUNIT::TestCase
112
130
  assert_equal(1, LongMath.gcd_with_high_power(n, 3), "3-part of 224 is 1")
113
131
  end
114
132
 
133
+ #
134
+ # test multiplicity_of_factor for integers
135
+ #
115
136
  def test_multiplicity_of_factor
116
137
  n = 224
117
138
  assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(224) is 5")
@@ -119,6 +140,9 @@ class TestLongDecimal_class < RUNIT::TestCase
119
140
  assert_equal(0, LongMath.multiplicity_of_factor(n, 3), "ny_3(224) is 0")
120
141
  end
121
142
 
143
+ #
144
+ # test multiplicity_of_factor for rationals
145
+ #
122
146
  def test_rat_multiplicity_of_factor
123
147
  n = Rational(224, 225)
124
148
  assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(n) is 5")
@@ -128,6 +152,10 @@ class TestLongDecimal_class < RUNIT::TestCase
128
152
  assert_equal(0, LongMath.multiplicity_of_factor(n, 11), "ny_11(n) is 0")
129
153
  end
130
154
 
155
+ #
156
+ # test multiplicity_of_factor for rationals with numerator and
157
+ # denominator exceeding Float
158
+ #
131
159
  def test_rat_long_multiplicity_of_factor
132
160
  n = Rational(224*(10**600+1), 225*(5**800))
133
161
  assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(n) is 5")
@@ -137,6 +165,22 @@ class TestLongDecimal_class < RUNIT::TestCase
137
165
  assert_equal(0, LongMath.multiplicity_of_factor(n, 11), "ny_11(n) is 0")
138
166
  end
139
167
 
168
+ #
169
+ # test multiplicity_of_factor for LongDecimal
170
+ #
171
+ def test_rat_multiplicity_of_factor
172
+ # 0.729
173
+ n = LongDecimal(729, 3)
174
+ assert_equal(-3, LongMath.multiplicity_of_factor(n, 2), "ny_2(n) is -3")
175
+ assert_equal(6, LongMath.multiplicity_of_factor(n, 3), "ny_3(n) is 6")
176
+ assert_equal(-3, LongMath.multiplicity_of_factor(n, 5), "ny_5(n) is -3")
177
+ assert_equal(0, LongMath.multiplicity_of_factor(n, 7), "ny_7(n) is 0")
178
+ assert_equal(0, LongMath.multiplicity_of_factor(n, 11), "ny_11(n) is 0")
179
+ end
180
+
181
+ #
182
+ # test construction from Integer
183
+ #
140
184
  def test_int_init
141
185
  l = LongDecimal(224)
142
186
  assert_equal(224, l.to_i, "no loss of information for integers allowed")
@@ -148,6 +192,9 @@ class TestLongDecimal_class < RUNIT::TestCase
148
192
  assert_equal(1, l.to_i, "loss of information 1.9->1")
149
193
  end
150
194
 
195
+ #
196
+ # test construction from Rational
197
+ #
151
198
  def test_rat_init
152
199
  r = Rational(227, 100)
153
200
  l = LongDecimal(r)
@@ -159,6 +206,9 @@ class TestLongDecimal_class < RUNIT::TestCase
159
206
  assert((r - l.to_r).to_f.abs < 0.01, "difference of #{r.inspect} and #{l.inspect} must be less 0.01 but is #{(r - l.to_r).to_f.abs}")
160
207
  end
161
208
 
209
+ #
210
+ # test construction from Float
211
+ #
162
212
  def test_float_init
163
213
  s = "5.32"
164
214
  l = LongDecimal(s)
@@ -171,6 +221,24 @@ class TestLongDecimal_class < RUNIT::TestCase
171
221
  assert_equal("0.000271", l.to_s, "l=#{l.inspect} f=#{f.inspect}")
172
222
  end
173
223
 
224
+ #
225
+ # test construction from BigDecimal
226
+ #
227
+ def test_bd_init
228
+ b = BigDecimal("5.32")
229
+ l = LongDecimal(b)
230
+ assert_equal(b, l.to_bd, "l=#{l.inspect}")
231
+ b = BigDecimal("2.24")
232
+ l = LongDecimal(b)
233
+ assert((b.to_f - l.to_f).abs < 1e-9, "l=#{l.inspect} b=#{b.inspect}")
234
+ b = BigDecimal("2.71E-4")
235
+ l = LongDecimal(b)
236
+ assert_equal("0.000271", l.to_s, "l=#{l.inspect} b=#{b.inspect}")
237
+ end
238
+
239
+ #
240
+ # test rounding with ROUND_UP
241
+ #
174
242
  def test_round_to_scale_up
175
243
  l = LongDecimal("2.21")
176
244
  r = l.round_to_scale(1, LongDecimal::ROUND_UP)
@@ -193,6 +261,9 @@ class TestLongDecimal_class < RUNIT::TestCase
193
261
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
194
262
  end
195
263
 
264
+ #
265
+ # test rounding with ROUND_DOWN
266
+ #
196
267
  def test_round_to_scale_down
197
268
  l = LongDecimal("2.29")
198
269
  r = l.round_to_scale(1, LongDecimal::ROUND_DOWN)
@@ -215,6 +286,9 @@ class TestLongDecimal_class < RUNIT::TestCase
215
286
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
216
287
  end
217
288
 
289
+ #
290
+ # test rounding with ROUND_CEILING
291
+ #
218
292
  def test_round_to_scale_ceiling
219
293
  l = LongDecimal("2.21")
220
294
  r = l.round_to_scale(1, LongDecimal::ROUND_CEILING)
@@ -237,6 +311,9 @@ class TestLongDecimal_class < RUNIT::TestCase
237
311
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
238
312
  end
239
313
 
314
+ #
315
+ # test rounding with ROUND_FLOOR
316
+ #
240
317
  def test_round_to_scale_floor
241
318
  l = LongDecimal("2.29")
242
319
  r = l.round_to_scale(1, LongDecimal::ROUND_FLOOR)
@@ -259,6 +336,9 @@ class TestLongDecimal_class < RUNIT::TestCase
259
336
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
260
337
  end
261
338
 
339
+ #
340
+ # test rounding with ROUND_HALF_UP
341
+ #
262
342
  def test_round_to_scale_half_up
263
343
  l = LongDecimal("2.20")
264
344
  r = l.round_to_scale(1, LongDecimal::ROUND_HALF_UP)
@@ -297,6 +377,9 @@ class TestLongDecimal_class < RUNIT::TestCase
297
377
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
298
378
  end
299
379
 
380
+ #
381
+ # test rounding with ROUND_HALF_DOWN
382
+ #
300
383
  def test_round_to_scale_half_down
301
384
  l = LongDecimal("2.20")
302
385
  r = l.round_to_scale(1, LongDecimal::ROUND_HALF_DOWN)
@@ -335,6 +418,9 @@ class TestLongDecimal_class < RUNIT::TestCase
335
418
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
336
419
  end
337
420
 
421
+ #
422
+ # test rounding with ROUND_HALF_EVEN
423
+ #
338
424
  def test_round_to_scale_half_even
339
425
  l = LongDecimal("2.20")
340
426
  r = l.round_to_scale(1, LongDecimal::ROUND_HALF_EVEN)
@@ -381,6 +467,9 @@ class TestLongDecimal_class < RUNIT::TestCase
381
467
  assert_equal("2.2400", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
382
468
  end
383
469
 
470
+ #
471
+ # test rounding with ROUND_UNNECESSARY
472
+ #
384
473
  def test_round_to_scale_unnecessary
385
474
  l = LongDecimal("2.24")
386
475
  r = l.round_to_scale(4, LongDecimal::ROUND_UNNECESSARY)
@@ -397,6 +486,9 @@ class TestLongDecimal_class < RUNIT::TestCase
397
486
  end
398
487
  end
399
488
 
489
+ #
490
+ # test conversion to String
491
+ #
400
492
  def test_to_s
401
493
  l = LongDecimal(224, 0)
402
494
  assert_equal("224", l.to_s, "l=#{l.inspect}")
@@ -421,6 +513,9 @@ class TestLongDecimal_class < RUNIT::TestCase
421
513
  assert_equal("-0.0224", l.to_s, "l=#{l.inspect}")
422
514
  end
423
515
 
516
+ #
517
+ # test conversion to Rational
518
+ #
424
519
  def test_to_r
425
520
  l = LongDecimal(224, 0)
426
521
  assert_equal(l, l.to_r.to_ld, "l=#{l.inspect}")
@@ -434,6 +529,9 @@ class TestLongDecimal_class < RUNIT::TestCase
434
529
  assert_equal(l, l.to_r.to_ld, "l=#{l.inspect}")
435
530
  end
436
531
 
532
+ #
533
+ # test conversion to Float
534
+ #
437
535
  def test_to_f
438
536
  l = LongDecimal(224, 0)
439
537
  assert((l.to_f - 224).abs < 224 * 0.000001, "l=#{l.inspect}")
@@ -447,6 +545,25 @@ class TestLongDecimal_class < RUNIT::TestCase
447
545
  assert((l.to_f - 0.0224).abs < 0.0224 * 0.000001, "l=#{l.inspect}")
448
546
  end
449
547
 
548
+ #
549
+ # test conversion to BigDecimal
550
+ #
551
+ def test_to_bd
552
+ l = LongDecimal(224, 0)
553
+ assert((l.to_bd - 224).abs < 224 * 0.000001, "l=#{l.inspect}")
554
+ l = LongDecimal(224, 1)
555
+ assert((l.to_bd - 22.4).abs < 22.4 * 0.000001, "l=#{l.inspect}")
556
+ l = LongDecimal(224, 2)
557
+ assert((l.to_bd - 2.24).abs < 2.24 * 0.000001, "l=#{l.inspect}")
558
+ l = LongDecimal(224, 3)
559
+ assert((l.to_bd - 0.224).abs < 0.224 * 0.000001, "l=#{l.inspect}")
560
+ l = LongDecimal(224, 4)
561
+ assert((l.to_bd - 0.0224).abs < 0.0224 * 0.000001, "l=#{l.inspect}")
562
+ end
563
+
564
+ #
565
+ # test conversion to Integer
566
+ #
450
567
  def test_to_i
451
568
  l = LongDecimal(224, 0)
452
569
  assert_equal(224, l.to_i, "l=#{l.inspect}")
data/version.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  #
4
4
  # version.rb -- extract version information from files
5
5
  #
6
- # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/version.rb,v 1.3 2006/02/25 20:05:53 bk1 Exp $
7
- # CVS-Label: $Name: PRE_ALPHA_0_06 $
6
+ # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/version.rb,v 1.4 2006/03/02 20:33:55 bk1 Exp $
7
+ # CVS-Label: $Name: PRE_ALPHA_0_08 $
8
8
  # Author: $Author: bk1 $ (Karl Brodowsky)
9
9
  #
10
10
 
@@ -24,7 +24,7 @@ ARGV.each do |file|
24
24
 
25
25
  str = ""
26
26
  if name =~ /PRE_ALPHA_(\d+)_(\d+)/ then
27
- str = sprintf("0.%02d.%02d", $1, $2)
27
+ str = sprintf("0.%02d.%02d", $1.to_i, $2.to_i)
28
28
  else
29
29
  str = version
30
30
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: long-decimal
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.00.07
7
- date: 2006-02-28 00:00:00 +01:00
6
+ version: 0.00.08
7
+ date: 2006-03-02 00:00:00 +01:00
8
8
  summary: LongDecimal for numbers with fixed point
9
9
  require_paths:
10
10
  - lib