3 # The following hash values are used:
4 # sign : +,-,NaN,+inf,-inf
6 # _n : numeraotr (value = _n/_d)
9 # _f : flags, used by MBR to flag parts of a rational as untouchable
18 use vars qw($VERSION @ISA $PACKAGE @EXPORT_OK $upgrade $downgrade
19 $accuracy $precision $round_mode $div_scale);
21 @ISA = qw(Exporter Math::BigFloat);
26 use overload; # inherit from Math::BigFloat
28 ##############################################################################
29 # global constants, flags and accessory
31 use constant MB_NEVER_ROUND => 0x0001;
33 $accuracy = $precision = undef;
40 my $class = 'Math::BigRat';
41 my $MBI = 'Math::BigInt';
45 return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
51 # turn a single float input into a rational (like '0.1')
54 return $self->bnan() if $f->is_nan();
55 return $self->binf('-inf') if $f->{sign} eq '-inf';
56 return $self->binf('+inf') if $f->{sign} eq '+inf';
58 #print "f $f caller", join(' ',caller()),"\n";
59 $self->{_n} = $f->{_m}->copy(); # mantissa
60 $self->{_d} = $MBI->bone();
61 $self->{sign} = $f->{sign}; $self->{_n}->{sign} = '+';
62 if ($f->{_e}->{sign} eq '-')
64 # something like Math::BigRat->new('0.1');
65 $self->{_d}->blsft($f->{_e}->copy()->babs(),10); # 1 / 1 => 1/10
69 # something like Math::BigRat->new('10');
71 $self->{_n}->blsft($f->{_e},10) unless $f->{_e}->is_zero();
73 # print "float new $self->{_n} / $self->{_d}\n";
79 # create a Math::BigRat
84 my $self = { }; bless $self,$class;
86 # print "ref ",ref($n),"\n";
89 # print "isa float " if $n->isa('Math::BigFloat');
90 # print "isa int " if $n->isa('Math::BigInt');
91 # print "isa rat " if $n->isa('Math::BigRat');
92 # print "isa lite " if $n->isa('Math::BigInt::Lite');
96 # print "scalar $n\n";
98 # input like (BigInt,BigInt) or (BigFloat,BigFloat) not handled yet
100 if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
102 # print "is ref, but not rat\n";
103 if ($n->isa('Math::BigFloat'))
105 # print "is ref, and float\n";
106 return $self->_new_from_float($n)->bnorm();
108 if ($n->isa('Math::BigInt'))
110 $self->{_n} = $n->copy(); # "mantissa" = $n
111 $self->{_d} = $MBI->bone();
112 $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
113 return $self->bnorm();
115 if ($n->isa('Math::BigInt::Lite'))
117 # print "is ref, and lite\n";
118 $self->{_n} = $MBI->new($$n); # "mantissa" = $n
119 $self->{_d} = $MBI->bone();
120 $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
121 return $self->bnorm();
124 return $n->copy() if ref $n;
126 # print "is string\n";
130 $self->{_n} = $MBI->bzero(); # undef => 0
131 $self->{_d} = $MBI->bone();
133 return $self->bnorm();
135 # string input with / delimiter
136 if ($n =~ /\s*\/\s*/)
138 return Math::BigRat->bnan() if $n =~ /\/.*\//; # 1/2/3 isn't valid
139 return Math::BigRat->bnan() if $n =~ /\/\s*$/; # 1/ isn't valid
140 ($n,$d) = split (/\//,$n);
141 # try as BigFloats first
142 if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
144 # one of them looks like a float
145 $self->_new_from_float(Math::BigFloat->new($n));
146 # now correct $self->{_n} due to $n
147 my $f = Math::BigFloat->new($d);
148 if ($f->{_e}->{sign} eq '-')
151 $self->{_n}->blsft($f->{_e}->copy()->babs(),10);
155 $self->{_d}->blsft($f->{_e},10); # 1 / 1 => 10/1
160 $self->{_n} = $MBI->new($n);
161 $self->{_d} = $MBI->new($d);
162 return $self->bnan() if $self->{_n}->is_nan() || $self->{_d}->is_nan();
163 # inf handling is missing here
165 $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
166 # if $d is negative, flip sign
167 $self->{sign} =~ tr/+-/-+/ if $self->{_d}->{sign} eq '-';
168 $self->{_d}->{sign} = '+'; # normalize
170 return $self->bnorm();
173 # simple string input
174 if (($n =~ /[\.eE]/))
177 # print "float-like string $d\n";
178 $self->_new_from_float(Math::BigFloat->new($n));
182 $self->{_n} = $MBI->new($n);
183 $self->{_d} = $MBI->bone();
184 $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
189 ###############################################################################
193 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
195 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
197 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
201 # print "bstr $x->{sign} $x->{_n} $x->{_d}\n";
202 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
204 return $s.$x->{_n}->bstr() if $x->{_d}->is_one();
205 return $s.$x->{_n}->bstr() . '/' . $x->{_d}->bstr();
210 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
212 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
214 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
218 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
219 return $x->{_n}->bstr() . '/' . $x->{_d}->bstr();
224 # reduce the number to the shortest form and remember this (so that we
225 # don't reduce again)
226 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
228 # both parts must be BigInt's
229 die ("n is not $MBI but (".ref($x->{_n}).')')
230 if ref($x->{_n}) ne $MBI;
231 die ("d is not $MBI but (".ref($x->{_d}).')')
232 if ref($x->{_d}) ne $MBI;
234 # this is to prevent automatically rounding when MBI's globals are set
235 $x->{_d}->{_f} = MB_NEVER_ROUND;
236 $x->{_n}->{_f} = MB_NEVER_ROUND;
237 # 'forget' that parts were rounded via MBI::bround() in MBF's bfround()
238 $x->{_d}->{_a} = undef; $x->{_n}->{_a} = undef;
239 $x->{_d}->{_p} = undef; $x->{_n}->{_p} = undef;
241 # print "$x->{sign} $x->{_n} / $x->{_d} => ";
243 # no normalize for NaN, inf etc.
244 return $x if $x->{sign} !~ /^[+-]$/;
246 # normalize zeros to 0/1
247 if (($x->{sign} =~ /^[+-]$/) &&
248 ($x->{_n}->is_zero()))
250 $x->{sign} = '+'; # never -0
251 $x->{_d} = $MBI->bone() unless $x->{_d}->is_one();
255 return $x if $x->{_d}->is_one();
257 # reduce other numbers
258 # print "bgcd $x->{_n} (",ref($x->{_n}),") $x->{_d} (",ref($x->{_d}),")\n";
259 # disable upgrade in BigInt, otherwise deep recursion
260 local $Math::BigInt::upgrade = undef;
261 my $gcd = $x->{_n}->bgcd($x->{_d});
265 # print "normalize $x->{_d} / $x->{_n} => ";
266 $x->{_n}->bdiv($gcd);
267 $x->{_d}->bdiv($gcd);
268 # print "$x->{_d} / $x->{_n}\n";
270 # print "$x->{_n} / $x->{_d}\n";
274 ##############################################################################
279 # used by parent class bone() to initialize number to 1
281 $self->{_n} = Math::BigInt->bzero();
282 $self->{_d} = Math::BigInt->bzero();
287 # used by parent class bone() to initialize number to 1
289 $self->{_n} = Math::BigInt->bzero();
290 $self->{_d} = Math::BigInt->bzero();
295 # used by parent class bone() to initialize number to 1
297 $self->{_n} = Math::BigInt->bone();
298 $self->{_d} = Math::BigInt->bone();
303 # used by parent class bone() to initialize number to 1
305 $self->{_n} = Math::BigInt->bzero();
306 $self->{_d} = Math::BigInt->bone();
309 ##############################################################################
315 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
317 # print "rat badd\n";
318 # print "ref($x) = ",ref($x),"\n";
319 # print "ref($y) = ",ref($y),"\n";
320 $x = $self->new($x) unless $x->isa($self);
321 $y = $self->new($y) unless $y->isa($self);
322 # print "ref($x) = ",ref($x),"\n";
323 # print "ref($y) = ",ref($y),"\n";
325 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
327 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
328 # - + - = --------- = --
331 my $gcd = $x->{_d}->bgcd($y->{_d});
333 my $aa = $x->{_d}->copy();
334 my $bb = $y->{_d}->copy();
337 $bb->bdiv($gcd); $aa->bdiv($gcd);
339 $x->{_n}->bmul($bb); $x->{_n}->{sign} = $x->{sign};
340 my $m = $y->{_n}->copy()->bmul($aa);
341 $m->{sign} = $y->{sign}; # 2/1 - 2/1
344 $x->{_d}->bmul($y->{_d});
347 $x->{sign} = $x->{_n}->{sign}; $x->{_n}->{sign} = '+';
349 $x->bnorm()->round($a,$p,$r);
354 # subtract two rationals
355 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
357 $x = $class->new($x) unless $x->isa($class);
358 $y = $class->new($y) unless $y->isa($class);
360 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
363 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
364 # - + - = --------- = --
367 my $gcd = $x->{_d}->bgcd($y->{_d});
369 my $aa = $x->{_d}->copy();
370 my $bb = $y->{_d}->copy();
373 $bb->bdiv($gcd); $aa->bdiv($gcd);
375 $x->{_n}->bmul($bb); $x->{_n}->{sign} = $x->{sign};
376 my $m = $y->{_n}->copy()->bmul($aa);
377 $m->{sign} = $y->{sign}; # 2/1 - 2/1
380 $x->{_d}->bmul($y->{_d});
383 $x->{sign} = $x->{_n}->{sign}; $x->{_n}->{sign} = '+';
385 $x->bnorm()->round($a,$p,$r);
390 # multiply two rationals
391 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
393 $x = $class->new($x) unless $x->isa($class);
394 $y = $class->new($y) unless $y->isa($class);
396 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
399 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
401 return $x->bnan() if $x->is_zero() || $y->is_zero();
402 # result will always be +-inf:
403 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
404 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
405 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
406 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
407 return $x->binf('-');
410 # x== 0 # also: or y == 1 or y == -1
411 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
413 # According to Knuth, this can be optimized by doingtwice gcd (for d and n)
414 # and reducing in one step)
419 $x->{_n}->bmul($y->{_n});
420 $x->{_d}->bmul($y->{_d});
423 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
425 $x->bnorm()->round($a,$p,$r);
430 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
431 # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
432 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
434 $x = $class->new($x) unless $x->isa($class);
435 $y = $class->new($y) unless $y->isa($class);
437 # print "rat bdiv $x $y ",ref($x)," ",ref($y),"\n";
438 return $self->_div_inf($x,$y)
439 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
441 # x== 0 # also: or y == 1 or y == -1
442 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
444 # TODO: list context, upgrade
449 $x->{_n}->bmul($y->{_d});
450 $x->{_d}->bmul($y->{_n});
452 # print "result $x->{_d} $x->{_n}\n";
454 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
456 $x->bnorm()->round($a,$p,$r);
457 # print "result $x->{_d} $x->{_n}\n";
461 ##############################################################################
462 # is_foo methods (the rest is inherited)
466 # return true if arg (BRAT or num_str) is an integer
467 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
469 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
470 $x->{_d}->is_one(); # 1e-1 => no integer
476 # return true if arg (BRAT or num_str) is zero
477 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
479 return 1 if $x->{sign} eq '+' && $x->{_n}->is_zero();
485 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
486 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
488 my $sign = shift || ''; $sign = '+' if $sign ne '-';
490 if ($x->{sign} eq $sign && $x->{_n}->is_one() && $x->{_d}->is_one());
496 # return true if arg (BFLOAT or num_str) is odd or false if even
497 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
499 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
500 ($x->{_d}->is_one() && $x->{_n}->is_odd()); # x/2 is not, but 3/1
506 # return true if arg (BINT or num_str) is even or false if odd
507 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
509 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
510 return 1 if ($x->{_d}->is_one() # x/3 is never
511 && $x->{_n}->is_even()); # but 4/1 is
517 *objectify = \&Math::BigInt::objectify;
520 ##############################################################################
521 # parts() and friends
525 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
527 my $n = $x->{_n}->copy(); $n->{sign} = $x->{sign};
533 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
540 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
542 my $n = $x->{_n}->copy();
543 $n->{sign} = $x->{sign};
544 return ($x->{_n}->copy(),$x->{_d}->copy());
557 ##############################################################################
558 # special calc routines
562 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
564 return $x unless $x->{sign} =~ /^[+-]$/;
565 return $x if $x->{_d}->is_one(); # 22/1 => 22, 0/1 => 0
567 $x->{_n}->bdiv($x->{_d}); # 22/7 => 3/1
569 $x->{_n}->binc() if $x->{sign} eq '+'; # +22/7 => 4/1
575 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
577 return $x unless $x->{sign} =~ /^[+-]$/;
578 return $x if $x->{_d}->is_one(); # 22/1 => 22, 0/1 => 0
580 $x->{_n}->bdiv($x->{_d}); # 22/7 => 3/1
582 $x->{_n}->binc() if $x->{sign} eq '-'; # -22/7 => -4/1
588 return Math::BigRat->bnan();
593 my ($self,$x,$y,@r) = objectify(2,@_);
595 return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
596 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
597 return $x->bone(@r) if $y->is_zero();
598 return $x->round(@r) if $x->is_one() || $y->is_one();
599 if ($x->{sign} eq '-' && $x->{_n}->is_one() && $x->{_d}->is_one())
601 # if $x == -1 and odd/even y => +1/-1
602 return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
603 # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
605 # 1 ** -y => 1 / (1 ** |y|)
606 # so do test for negative $y after above's clause
607 # return $x->bnan() if $y->{sign} eq '-';
608 return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
610 my $pow2 = $self->__one();
611 my $y1 = Math::BigInt->new($y->{_n}/$y->{_d})->babs();
612 my $two = Math::BigInt->new(2);
613 while (!$y1->is_one())
615 print "at $y1 (= $x)\n";
616 $pow2->bmul($x) if $y1->is_odd();
620 $x->bmul($pow2) unless $pow2->is_one();
621 # n ** -x => 1/n ** x
622 ($x->{_d},$x->{_n}) = ($x->{_n},$x->{_d}) if $y->{sign} eq '-';
629 return Math::BigRat->bnan();
634 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
636 return $x->bnan() if $x->{sign} ne '+'; # inf, NaN, -1 etc
637 $x->{_d}->bsqrt($a,$p,$r);
638 $x->{_n}->bsqrt($a,$p,$r);
644 my ($self,$x,$y,$b,$a,$p,$r) = objectify(3,@_);
646 $x->bmul( $b->copy()->bpow($y), $a,$p,$r);
652 my ($self,$x,$y,$b,$a,$p,$r) = objectify(2,@_);
654 $x->bdiv( $b->copy()->bpow($y), $a,$p,$r);
658 ##############################################################################
676 ##############################################################################
681 my ($self,$x,$y) = objectify(2,@_);
683 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
685 # handle +-inf and NaN
686 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
687 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
688 return +1 if $x->{sign} eq '+inf';
689 return -1 if $x->{sign} eq '-inf';
690 return -1 if $y->{sign} eq '+inf';
693 # check sign for speed first
694 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
695 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
698 my $xz = $x->{_n}->is_zero();
699 my $yz = $y->{_n}->is_zero();
700 return 0 if $xz && $yz; # 0 <=> 0
701 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
702 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
704 my $t = $x->{_n} * $y->{_d}; $t->{sign} = $x->{sign};
705 my $u = $y->{_n} * $x->{_d}; $u->{sign} = $y->{sign};
711 my ($self,$x,$y) = objectify(2,@_);
713 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
715 # handle +-inf and NaN
716 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
717 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
718 return +1; # inf is always bigger
721 my $t = $x->{_n} * $y->{_d};
722 my $u = $y->{_n} * $x->{_d};
726 ##############################################################################
727 # output conversation
731 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
733 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf etc
734 my $t = $x->{_n}->copy()->bdiv($x->{_d}); # 22/7 => 3
735 $t->{sign} = $x->{sign};
744 for ( my $i = 0; $i < $l ; $i++)
746 # print "at $_[$i] (",$_[$i+1]||'undef',")\n";
747 if ( $_[$i] eq ':constant' )
749 # this rest causes overlord er load to step in
750 # print "overload @_\n";
751 overload::constant float => sub { $self->new(shift); };
753 # elsif ($_[$i] eq 'upgrade')
755 # # this causes upgrading
756 # $upgrade = $_[$i+1]; # or undef to disable
759 elsif ($_[$i] eq 'downgrade')
761 # this causes downgrading
762 $downgrade = $_[$i+1]; # or undef to disable
765 elsif ($_[$i] eq 'lib')
767 $lib = $_[$i+1] || ''; # default Calc
770 elsif ($_[$i] eq 'with')
772 $MBI = $_[$i+1] || 'Math::BigInt'; # default Math::BigInt
780 # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work
781 my $mbilib = eval { Math::BigInt->config()->{lib} };
782 if ((defined $mbilib) && ($MBI eq 'Math::BigInt'))
785 $MBI->import('lib',"$lib,$mbilib", 'objectify');
789 # MBI not loaded, or with ne "Math::BigInt"
790 $lib .= ",$mbilib" if defined $mbilib;
792 # my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt
793 # my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm
794 # $file = File::Spec->catfile (@parts, $file);
798 # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is
799 # used in the same script, or eval inside import().
800 my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt
801 my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm
802 $file = File::Spec->catfile (@parts, $file);
803 eval { require $file; $MBI->import( lib => '$lib', 'objectify' ); }
807 my $rc = "use $MBI lib => '$lib', 'objectify';";
811 die ("Couldn't load $MBI: $! $@") if $@;
813 # any non :constant stuff is handled by our parent, Exporter
814 # even if @_ is empty, to give it a chance
815 $self->SUPER::import(@a); # for subclasses
816 $self->export_to_level(1,$self,@a); # need this, too
825 Math::BigRat - arbitrarily big rationals
831 $x = Math::BigRat->new('3/7');
833 print $x->bstr(),"\n";
837 This is just a placeholder until the real thing is up and running. Watch this
842 Math with the numbers is done (by default) by a module called
843 Math::BigInt::Calc. This is equivalent to saying:
845 use Math::BigRat lib => 'Calc';
847 You can change this by using:
849 use Math::BigRat lib => 'BitVect';
851 The following would first try to find Math::BigInt::Foo, then
852 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
854 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
856 Calc.pm uses as internal format an array of elements of some decimal base
857 (usually 1e7, but this might be differen for some systems) with the least
858 significant digit first, while BitVect.pm uses a bit vector of base 2, most
859 significant bit first. Other modules might use even different means of
860 representing the numbers. See the respective module documentation for further
865 Any method not listed here is dervied from Math::BigFloat (or
866 Math::BigInt), so make sure you check these two modules for further
871 $x = Math::BigRat->new('1/3');
873 Create a new Math::BigRat object. Input can come in various forms:
875 $x = Math::BigRat->new('1/3'); # simple string
876 $x = Math::BigRat->new('1 / 3'); # spaced
877 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
878 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
879 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
880 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
884 $n = $x->numerator();
886 Returns a copy of the numerator (the part above the line) as signed BigInt.
890 $d = $x->denominator();
892 Returns a copy of the denominator (the part under the line) as positive BigInt.
896 ($n,$d) = $x->parts();
898 Return a list consisting of (signed) numerator and (unsigned) denominator as
903 Returns a copy of the object as BigInt by truncating it to integer.
907 Are not yet implemented.
909 =head2 bround()/round()/bfround()
911 Are not yet implemented.
918 =item perl -Mbigrat -le 'print 1 + 2/3'
920 This produces wrongly NaN. It is unclear why. The following variants all work:
922 perl -Mbigrat -le 'print 1/3 + 2/3'
923 perl -Mbigrat -le 'print 1/3 + 2'
925 This also does not work:
927 perl -Mbigrat -le 'print 1+3+1/2'
931 Please see also L<Math::BigInt>.
935 This program is free software; you may redistribute it and/or modify it under
936 the same terms as Perl itself.
940 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
941 L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
944 L<http://search.cpan.org/search?mode=module&query=Math%3A%3ABigRat> may
945 contain more documentation and examples as well as testcases.
949 (C) by Tels L<http://bloodgate.com/> 2001-2002.