# The following hash values are used:
# sign : +,-,NaN,+inf,-inf
# _n : numeraotr (value = _n/_d)
# _f : flags, used by MBR to flag parts of a rational as untouchable
use vars
qw($VERSION @ISA $PACKAGE @EXPORT_OK $upgrade $downgrade
$accuracy $precision $round_mode $div_scale);
@ISA = qw(Exporter Math::BigFloat);
use overload
; # inherit from Math::BigFloat
##############################################################################
# global constants, flags and accessory
use constant MB_NEVER_ROUND
=> 0x0001;
$accuracy = $precision = undef;
my $class = 'Math::BigRat';
my $MBI = 'Math::BigInt';
return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
# turn a single float input into a rational (like '0.1')
return $self->bnan() if $f->is_nan();
return $self->binf('-inf') if $f->{sign
} eq '-inf';
return $self->binf('+inf') if $f->{sign
} eq '+inf';
#print "f $f caller", join(' ',caller()),"\n";
$self->{_n
} = $f->{_m
}->copy(); # mantissa
$self->{_d
} = $MBI->bone();
$self->{sign
} = $f->{sign
}; $self->{_n
}->{sign
} = '+';
if ($f->{_e
}->{sign
} eq '-')
# something like Math::BigRat->new('0.1');
$self->{_d
}->blsft($f->{_e
}->copy()->babs(),10); # 1 / 1 => 1/10
# something like Math::BigRat->new('10');
$self->{_n
}->blsft($f->{_e
},10) unless $f->{_e
}->is_zero();
my $self = { }; bless $self,$class;
# input like (BigInt,BigInt) or (BigFloat,BigFloat) not handled yet
if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
if ($n->isa('Math::BigFloat'))
return $self->_new_from_float($n)->bnorm();
if ($n->isa('Math::BigInt'))
$self->{_n
} = $n->copy(); # "mantissa" = $n
$self->{_d
} = $MBI->bone();
$self->{sign
} = $self->{_n
}->{sign
}; $self->{_n
}->{sign
} = '+';
if ($n->isa('Math::BigInt::Lite'))
$self->{_n
} = $MBI->new($$n); # "mantissa" = $n
$self->{_d
} = $MBI->bone();
$self->{sign
} = $self->{_n
}->{sign
}; $self->{_n
}->{sign
} = '+';
return $n->copy() if ref $n;
$self->{_n
} = $MBI->bzero(); # undef => 0
$self->{_d
} = $MBI->bone();
# string input with / delimiter
return Math
::BigRat
->bnan() if $n =~ /\/.*\
//; # 1/2/3 isn't valid
return Math
::BigRat
->bnan() if $n =~ /\/\s
*$/; # 1/ isn
't valid
($n,$d) = split (/\//,$n);
if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
# one of them looks like a float
$self->_new_from_float(Math::BigFloat->new($n));
# now correct $self->{_n} due to $n
my $f = Math::BigFloat->new($d);
if ($f->{_e}->{sign} eq '-')
$self->{_n}->blsft($f->{_e}->copy()->babs(),10);
$self->{_d}->blsft($f->{_e},10); # 1 / 1 => 10/1
$self->{_n} = $MBI->new($n);
$self->{_d} = $MBI->new($d);
return $self->bnan() if $self->{_n}->is_nan() || $self->{_d}->is_nan();
# inf handling is missing here
$self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
# if $d is negative, flip sign
$self->{sign} =~ tr/+-/-+/ if $self->{_d}->{sign} eq '-';
$self->{_d}->{sign} = '+'; # normalize
# work around bug in BigFloat that makes 1.1.2 valid
return $self->bnan() if $n =~ /\..*\./;
$self->_new_from_float(Math::BigFloat->new($n));
$self->{_n} = $MBI->new($n);
$self->{_d} = $MBI->bone();
$self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
return $self->bnan() if $self->{sign} eq 'NaN
';
return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
###############################################################################
my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
return $s.$x->{_n}->bstr() if $x->{_d}->is_one();
return $s.$x->{_n}->bstr() . '/' . $x->{_d}->bstr();
my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
return $x->{_n}->bstr() . '/' . $x->{_d}->bstr();
# reduce the number to the shortest form and remember this (so that we
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
# both parts must be BigInt's
die ("n is not $MBI but (".ref($x->{_n
}).')')
if ref($x->{_n
}) ne $MBI;
die ("d is not $MBI but (".ref($x->{_d
}).')')
if ref($x->{_d
}) ne $MBI;
# this is to prevent automatically rounding when MBI's globals are set
$x->{_d
}->{_f
} = MB_NEVER_ROUND
;
$x->{_n
}->{_f
} = MB_NEVER_ROUND
;
# 'forget' that parts were rounded via MBI::bround() in MBF's bfround()
$x->{_d
}->{_a
} = undef; $x->{_n
}->{_a
} = undef;
$x->{_d
}->{_p
} = undef; $x->{_n
}->{_p
} = undef;
# no normalize for NaN, inf etc.
return $x if $x->{sign
} !~ /^[+-]$/;
if (($x->{sign
} =~ /^[+-]$/) &&
$x->{sign
} = '+'; # never -0
$x->{_d
} = $MBI->bone() unless $x->{_d
}->is_one();
return $x if $x->{_d
}->is_one(); # no need to reduce
# disable upgrade in BigInt, otherwise deep recursion
local $Math::BigInt
::upgrade
= undef;
my $gcd = $x->{_n
}->bgcd($x->{_d
});
##############################################################################
# used by parent class bone() to initialize number to 1
$self->{_n
} = $MBI->bzero();
$self->{_d
} = $MBI->bzero();
# used by parent class bone() to initialize number to 1
$self->{_n
} = $MBI->bzero();
$self->{_d
} = $MBI->bzero();
# used by parent class bone() to initialize number to 1
$self->{_n
} = $MBI->bone();
$self->{_d
} = $MBI->bone();
# used by parent class bone() to initialize number to 1
$self->{_n
} = $MBI->bzero();
$self->{_d
} = $MBI->bone();
##############################################################################
my ($self,$x,$y,$a,$p,$r) = objectify
(2,@_);
$x = $self->new($x) unless $x->isa($self);
$y = $self->new($y) unless $y->isa($self);
return $x->bnan() if ($x->{sign
} eq 'NaN' || $y->{sign
} eq 'NaN');
# 1 1 gcd(3,4) = 1 1*3 + 1*4 7
my $gcd = $x->{_d
}->bgcd($y->{_d
});
my $aa = $x->{_d
}->copy();
my $bb = $y->{_d
}->copy();
$bb->bdiv($gcd); $aa->bdiv($gcd);
$x->{_n
}->bmul($bb); $x->{_n
}->{sign
} = $x->{sign
};
my $m = $y->{_n
}->copy()->bmul($aa);
$m->{sign
} = $y->{sign
}; # 2/1 - 2/1
$x->{_d
}->bmul($y->{_d
});
$x->{sign
} = $x->{_n
}->{sign
}; $x->{_n
}->{sign
} = '+';
$x->bnorm()->round($a,$p,$r);
my ($self,$x,$y,$a,$p,$r) = objectify
(2,@_);
$x = $class->new($x) unless $x->isa($class);
$y = $class->new($y) unless $y->isa($class);
return $x->bnan() if ($x->{sign
} eq 'NaN' || $y->{sign
} eq 'NaN');
# 1 1 gcd(3,4) = 1 1*3 + 1*4 7
my $gcd = $x->{_d
}->bgcd($y->{_d
});
my $aa = $x->{_d
}->copy();
my $bb = $y->{_d
}->copy();
$bb->bdiv($gcd); $aa->bdiv($gcd);
$x->{_n
}->bmul($bb); $x->{_n
}->{sign
} = $x->{sign
};
my $m = $y->{_n
}->copy()->bmul($aa);
$m->{sign
} = $y->{sign
}; # 2/1 - 2/1
$x->{_d
}->bmul($y->{_d
});
$x->{sign
} = $x->{_n
}->{sign
}; $x->{_n
}->{sign
} = '+';
$x->bnorm()->round($a,$p,$r);
my ($self,$x,$y,$a,$p,$r) = objectify
(2,@_);
$x = $class->new($x) unless $x->isa($class);
$y = $class->new($y) unless $y->isa($class);
return $x->bnan() if ($x->{sign
} eq 'NaN' || $y->{sign
} eq 'NaN');
if (($x->{sign
} =~ /^[+-]inf$/) || ($y->{sign
} =~ /^[+-]inf$/))
return $x->bnan() if $x->is_zero() || $y->is_zero();
# result will always be +-inf:
# +inf * +/+inf => +inf, -inf * -/-inf => +inf
# +inf * -/-inf => -inf, -inf * +/+inf => -inf
return $x->binf() if ($x->{sign
} =~ /^\+/ && $y->{sign
} =~ /^\+/);
return $x->binf() if ($x->{sign
} =~ /^-/ && $y->{sign
} =~ /^-/);
# x== 0 # also: or y == 1 or y == -1
return wantarray ?
($x,$self->bzero()) : $x if $x->is_zero();
# According to Knuth, this can be optimized by doingtwice gcd (for d and n)
# and reducing in one step)
$x->{_n
}->bmul($y->{_n
});
$x->{_d
}->bmul($y->{_d
});
$x->{sign
} = $x->{sign
} eq $y->{sign
} ?
'+' : '-';
$x->bnorm()->round($a,$p,$r);
# (dividend: BRAT or num_str, divisor: BRAT or num_str) return
# (BRAT,BRAT) (quo,rem) or BRAT (only rem)
my ($self,$x,$y,$a,$p,$r) = objectify
(2,@_);
$x = $class->new($x) unless $x->isa($class);
$y = $class->new($y) unless $y->isa($class);
return $self->_div_inf($x,$y)
if (($x->{sign
} !~ /^[+-]$/) || ($y->{sign
} !~ /^[+-]$/) || $y->is_zero());
# x== 0 # also: or y == 1 or y == -1
return wantarray ?
($x,$self->bzero()) : $x if $x->is_zero();
# TODO: list context, upgrade
$x->{_n
}->bmul($y->{_d
});
$x->{_d
}->bmul($y->{_n
});
$x->{sign
} = $x->{sign
} eq $y->{sign
} ?
'+' : '-';
$x->bnorm()->round($a,$p,$r);
##############################################################################
# decrement value (subtract 1)
my ($self,$x,@r) = ref($_[0]) ?
(ref($_[0]),@_) : objectify
(1,@_);
return $x if $x->{sign
} !~ /^[+-]$/; # NaN, inf, -inf
$x->{_n
}->badd($x->{_d
}); # -5/2 => -7/2
if ($x->{_n
}->bacmp($x->{_d
}) < 0)
$x->{_n
} = $x->{_d
} - $x->{_n
};
$x->{_n
}->bsub($x->{_d
}); # 5/2 => 3/2
#$x->bsub($self->bone())->round(@r);
# increment value (add 1)
my ($self,$x,@r) = ref($_[0]) ?
(ref($_[0]),@_) : objectify
(1,@_);
return $x if $x->{sign
} !~ /^[+-]$/; # NaN, inf, -inf
if ($x->{_n
}->bacmp($x->{_d
}) < 0)
# -1/3 ++ => 2/3 (overflow at 0)
$x->{_n
} = $x->{_d
} - $x->{_n
};
$x->{_n
}->bsub($x->{_d
}); # -5/2 => -3/2
$x->{_n
}->badd($x->{_d
}); # 5/2 => 7/2
#$x->badd($self->bone())->round(@r);
##############################################################################
# is_foo methods (the rest is inherited)
# return true if arg (BRAT or num_str) is an integer
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return 1 if ($x->{sign
} =~ /^[+-]$/) && # NaN and +-inf aren't
$x->{_d
}->is_one(); # 1e-1 => no integer
# return true if arg (BRAT or num_str) is zero
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return 1 if $x->{sign
} eq '+' && $x->{_n
}->is_zero();
# return true if arg (BRAT or num_str) is +1 or -1 if signis given
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
my $sign = shift || ''; $sign = '+' if $sign ne '-';
if ($x->{sign
} eq $sign && $x->{_n
}->is_one() && $x->{_d
}->is_one());
# return true if arg (BFLOAT or num_str) is odd or false if even
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return 1 if ($x->{sign
} =~ /^[+-]$/) && # NaN & +-inf aren't
($x->{_d
}->is_one() && $x->{_n
}->is_odd()); # x/2 is not, but 3/1
# return true if arg (BINT or num_str) is even or false if odd
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return 0 if $x->{sign
} !~ /^[+-]$/; # NaN & +-inf aren't
return 1 if ($x->{_d
}->is_one() # x/3 is never
&& $x->{_n
}->is_even()); # but 4/1 is
*objectify
= \
&Math
::BigInt
::objectify
;
##############################################################################
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $MBI->new($x->{sign
}) if ($x->{sign
} !~ /^[+-]$/);
my $n = $x->{_n
}->copy(); $n->{sign
} = $x->{sign
};
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $MBI->new($x->{sign
}) if ($x->{sign
} !~ /^[+-]$/);
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return ($self->bnan(),$self->bnan()) if $x->{sign
} eq 'NaN';
return ($self->binf(),$self->binf()) if $x->{sign
} eq '+inf';
return ($self->binf('-'),$self->binf()) if $x->{sign
} eq '-inf';
my $n = $x->{_n
}->copy();
return ($n,$x->{_d
}->copy());
##############################################################################
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $x unless $x->{sign
} =~ /^[+-]$/;
return $x if $x->{_d
}->is_one(); # 22/1 => 22, 0/1 => 0
$x->{_n
}->bdiv($x->{_d
}); # 22/7 => 3/1 w/ truncate
$x->{_n
}->binc() if $x->{sign
} eq '+'; # +22/7 => 4/1
$x->{sign
} = '+' if $x->{_n
}->is_zero(); # -0 => 0
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $x unless $x->{sign
} =~ /^[+-]$/;
return $x if $x->{_d
}->is_one(); # 22/1 => 22, 0/1 => 0
$x->{_n
}->bdiv($x->{_d
}); # 22/7 => 3/1 w/ truncate
$x->{_n
}->binc() if $x->{sign
} eq '-'; # -22/7 => -4/1
my ($self,$x,@r) = ref($_[0]) ?
(ref($_[0]),@_) : objectify
(1,@_);
if (($x->{sign
} eq '+') && ($x->{_d
}->is_one()))
my ($self,$x,$y,@r) = objectify
(2,@_);
return $x if $x->{sign
} =~ /^[+-]inf$/; # -inf/+inf ** x
return $x->bnan() if $x->{sign
} eq $nan || $y->{sign
} eq $nan;
return $x->bone(@r) if $y->is_zero();
return $x->round(@r) if $x->is_one() || $y->is_one();
if ($x->{sign
} eq '-' && $x->{_n
}->is_one() && $x->{_d
}->is_one())
# if $x == -1 and odd/even y => +1/-1
return $y->is_odd() ?
$x->round(@r) : $x->babs()->round(@r);
# my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
# 1 ** -y => 1 / (1 ** |y|)
# so do test for negative $y after above's clause
# return $x->bnan() if $y->{sign} eq '-';
return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
# shortcut y/1 (and/or x/1)
# shortcut for x/1 and y/1
$x->{_n
}->bpow($y->{_n
}); # x/1 ** y/1 => (x ** y)/1
# 0.2 ** -3 => 1/(0.2 ** 3)
($x->{_n
},$x->{_d
}) = ($x->{_d
},$x->{_n
}); # swap
# correct sign; + ** + => +
# - * - => +, - * - * - => -
$x->{sign
} = '+' if $y->{_n
}->is_even();
$x->{_n
}->bpow($y->{_n
}); # 5/2 ** y/1 => 5 ** y / 2 ** y
$x->{_d
}->bpow($y->{_n
});
# 0.2 ** -3 => 1/(0.2 ** 3)
($x->{_n
},$x->{_d
}) = ($x->{_d
},$x->{_n
}); # swap
# correct sign; + ** + => +
# - * - => +, - * - * - => -
$x->{sign
} = '+' if $y->{_n
}->is_even();
# regular calculation (this is wrong for d/e ** f/g)
my $pow2 = $self->__one();
my $y1 = $MBI->new($y->{_n
}/$y->{_d
})->babs();
$pow2->bmul($x) if $y1->is_odd();
$x->bmul($pow2) unless $pow2->is_one();
($x->{_d
},$x->{_n
}) = ($x->{_n
},$x->{_d
}) if $y->{sign
} eq '-';
return Math
::BigRat
->bnan();
my ($self,$x,$a,$p,$r) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $x->bnan() if $x->{sign
} ne '+'; # inf, NaN, -1 etc
$x->{_d
}->bsqrt($a,$p,$r);
$x->{_n
}->bsqrt($a,$p,$r);
my ($self,$x,$y,$b,$a,$p,$r) = objectify
(3,@_);
$x->bmul( $b->copy()->bpow($y), $a,$p,$r);
my ($self,$x,$y,$b,$a,$p,$r) = objectify
(2,@_);
$x->bdiv( $b->copy()->bpow($y), $a,$p,$r);
##############################################################################
##############################################################################
my ($self,$x,$y) = objectify
(2,@_);
if (($x->{sign
} !~ /^[+-]$/) || ($y->{sign
} !~ /^[+-]$/))
return undef if (($x->{sign
} eq $nan) || ($y->{sign
} eq $nan));
return 0 if $x->{sign
} eq $y->{sign
} && $x->{sign
} =~ /^[+-]inf$/;
return +1 if $x->{sign
} eq '+inf';
return -1 if $x->{sign
} eq '-inf';
return -1 if $y->{sign
} eq '+inf';
# check sign for speed first
return 1 if $x->{sign
} eq '+' && $y->{sign
} eq '-'; # does also 0 <=> -y
return -1 if $x->{sign
} eq '-' && $y->{sign
} eq '+'; # does also -x <=> 0
my $xz = $x->{_n
}->is_zero();
my $yz = $y->{_n
}->is_zero();
return 0 if $xz && $yz; # 0 <=> 0
return -1 if $xz && $y->{sign
} eq '+'; # 0 <=> +y
return 1 if $yz && $x->{sign
} eq '+'; # +x <=> 0
my $t = $x->{_n
} * $y->{_d
}; $t->{sign
} = $x->{sign
};
my $u = $y->{_n
} * $x->{_d
}; $u->{sign
} = $y->{sign
};
my ($self,$x,$y) = objectify
(2,@_);
if (($x->{sign
} !~ /^[+-]$/) || ($y->{sign
} !~ /^[+-]$/))
return undef if (($x->{sign
} eq $nan) || ($y->{sign
} eq $nan));
return 0 if $x->{sign
} =~ /^[+-]inf$/ && $y->{sign
} =~ /^[+-]inf$/;
return +1; # inf is always bigger
my $t = $x->{_n
} * $y->{_d
};
my $u = $y->{_n
} * $x->{_d
};
##############################################################################
my ($self,$x) = ref($_[0]) ?
(ref($_[0]),$_[0]) : objectify
(1,@_);
return $x if $x->{sign
} !~ /^[+-]$/; # NaN, inf etc
my $t = $x->{_n
}->copy()->bdiv($x->{_d
}); # 22/7 => 3
for ( my $i = 0; $i < $l ; $i++)
# print "at $_[$i] (",$_[$i+1]||'undef',")\n";
if ( $_[$i] eq ':constant' )
# this rest causes overlord er load to step in
overload
::constant float
=> sub { $self->new(shift); };
# elsif ($_[$i] eq 'upgrade')
# # this causes upgrading
# $upgrade = $_[$i+1]; # or undef to disable
elsif ($_[$i] eq 'downgrade')
# this causes downgrading
$downgrade = $_[$i+1]; # or undef to disable
$lib = $_[$i+1] || ''; # default Calc
$MBI = $_[$i+1] || 'Math::BigInt'; # default Math::BigInt
# let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work
my $mbilib = eval { Math
::BigInt
->config()->{lib
} };
if ((defined $mbilib) && ($MBI eq 'Math::BigInt'))
$MBI->import('lib',"$lib,$mbilib", 'objectify');
# MBI not loaded, or not with "Math::BigInt"
$lib .= ",$mbilib" if defined $mbilib;
# Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is
# used in the same script, or eval inside import().
my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt
my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm
$file = File
::Spec
->catfile (@parts, $file);
eval { require $file; $MBI->import( lib
=> '$lib', 'objectify' ); }
my $rc = "use $MBI lib => '$lib', 'objectify';";
die ("Couldn't load $MBI: $! $@") if $@
;
# any non :constant stuff is handled by our parent, Exporter
# even if @_ is empty, to give it a chance
$self->SUPER::import
(@a); # for subclasses
$self->export_to_level(1,$self,@a); # need this, too
Math::BigRat - arbitrarily big rationals
$x = Math::BigRat->new('3/7');
This is just a placeholder until the real thing is up and running. Watch this
Math with the numbers is done (by default) by a module called
Math::BigInt::Calc. This is equivalent to saying:
use Math::BigRat lib => 'Calc';
You can change this by using:
use Math::BigRat lib => 'BitVect';
The following would first try to find Math::BigInt::Foo, then
Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
Calc.pm uses as internal format an array of elements of some decimal base
(usually 1e7, but this might be differen for some systems) with the least
significant digit first, while BitVect.pm uses a bit vector of base 2, most
significant bit first. Other modules might use even different means of
representing the numbers. See the respective module documentation for further
Any method not listed here is dervied from Math::BigFloat (or
Math::BigInt), so make sure you check these two modules for further
$x = Math::BigRat->new('1/3');
Create a new Math::BigRat object. Input can come in various forms:
$x = Math::BigRat->new('1/3'); # simple string
$x = Math::BigRat->new('1 / 3'); # spaced
$x = Math::BigRat->new('1 / 0.1'); # w/ floats
$x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
$x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
$x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
Returns a copy of the numerator (the part above the line) as signed BigInt.
Returns a copy of the denominator (the part under the line) as positive BigInt.
Return a list consisting of (signed) numerator and (unsigned) denominator as
Returns a copy of the object as BigInt by truncating it to integer.
Calculates the factorial of $x. For instance:
print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
Only works for integers for now.
=head2 bround()/round()/bfround()
Some things are not yet implemented, or only implemented half-way.
This program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.
L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
L<http://search.cpan.org/search?mode=module&query=Math%3A%3ABigRat> may
contain more documentation and examples as well as testcases.
(C) by Tels L<http://bloodgate.com/> 2001-2002.