Skip to content

Commit 579656e

Browse files
committed
Fix up test failures with older BigFloat versions
Also, call it v1.20, not v1.2
1 parent 5c0bbdb commit 579656e

File tree

3 files changed

+31
-15
lines changed

3 files changed

+31
-15
lines changed

dist.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = Math-BaseCalc
2-
version = 1.017
2+
version = 1.020
33
author = Ken Williams <kwilliams@cpan.org>
44
license = Perl_5
55
copyright_holder = Ken Williams

lib/Math/BaseCalc.pm

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use strict;
44
use Carp;
55
use Math::BigInt;
66
use Math::BigFloat;
7+
use Scalar::Util;
78
use vars qw($VERSION);
8-
$VERSION = '1.2';
9+
$VERSION = '1.20';
910

1011
# configure some basic big number stuff
1112
Math::BigInt ->config({
@@ -85,7 +86,10 @@ sub from_base {
8586
my $poten_digits = int(length($str) * $self->{digit_strength}) + 16;
8687
Math::BigFloat->accuracy($poten_digits + 16);
8788
my $result = Math::BigFloat->new(0);
88-
$result = $result->as_int() unless $is_dec;
89+
unless ($is_dec) {
90+
Math::BigInt->accuracy($poten_digits + 16);
91+
$result = Math::BigInt->new( $result->ffround(0, 'trunc')->bstr() ); # as_int loses precision on older BigFloats
92+
}
8993

9094
# short-circuits
9195
unless ($is_dec || !$self->{digitset_name}) {
@@ -117,13 +121,20 @@ sub from_base {
117121
sub _from_accurate_return {
118122
my ($self, $result) = @_;
119123

124+
# Prior to 1.997, Math::BigFloat->numify would always return scientific
125+
# notation, even for the simpliest of numbers. This would cause test
126+
# failures and just look ugly in general. Since we still want to
127+
# support older Perls with core modules, this dualvar workaround was
128+
# necessary to maintain accuracy and still look reasonable as a string.
129+
120130
# never lose the accuracy
121131
my $rscalar = $result->numify();
122132
my $rstring = $result->bstr();
123133
$rstring =~ s/0+$// if ($rstring =~ /\./);
124134
$rstring =~ s/\.$//; # float to whole number
125-
# (the user can choose to put the string in a Math object if s/he so wishes)
126-
return $rstring eq ($rscalar + 0 . '') ? $result->numify() : $rstring;
135+
136+
# (the user can choose to put the scalar in a Math object if s/he so wishes)
137+
return Scalar::Util::dualvar($rscalar, $rstring);
127138
}
128139

129140
sub to_base {
@@ -139,7 +150,10 @@ sub to_base {
139150
my $poten_digits = length($num);
140151
Math::BigFloat->accuracy($poten_digits + 16);
141152
$num = Math::BigFloat->new($num);
142-
$num = $num->as_int() unless $is_dec && $self->{radix_char};
153+
unless ($is_dec && $self->{radix_char}) {
154+
Math::BigInt->accuracy($poten_digits + 16);
155+
$num = Math::BigInt->new( $num->ffround(0, 'trunc')->bstr() ); # as_int loses precision on older BigFloats
156+
}
143157

144158
# (hold off on this check until after the big number support)
145159
return $self->{neg_char}.$self->to_base( $num->bneg ) if $num < 0; # Handle negative numbers
@@ -163,8 +177,8 @@ sub to_base {
163177
# BigFloat's accuracy should counter this, but the $i check is
164178
# to make sure we don't get into an irrational/cyclic number loop
165179
while (($num != 0 || $i >= 0) && $i > -1024) {
166-
my $exp = Math::BigFloat->new($base);
167-
$exp = $i < 0 ? $exp->bpow($i) : $exp->as_int->bpow($i);
180+
my $exp = $i < 0 ? Math::BigFloat->new($base) : Math::BigInt->new($base);
181+
$exp = $exp->bpow($i);
168182
my $v = $num->copy()->bdiv($exp)->bfloor();
169183
$num -= $v * $exp; # this method is safer for fractionals
170184

@@ -193,7 +207,7 @@ Math::BaseCalc - Convert numbers between various bases
193207
194208
=head1 VERSION
195209
196-
version 1.2
210+
version 1.20
197211
198212
=head1 SYNOPSIS
199213
@@ -276,14 +290,14 @@ If C<NUMBER> is a C<Math::BigInt> object, C<to_base()> will still work
276290
fine and give you an exact result string. In fact, Math::Big* is loaded in
277291
the background, so big numbers are fully supported.
278292
279-
As of v1.2, C<to_base()> will give you fractional results if passed a
293+
As of v1.20, C<to_base()> will give you fractional results if passed a
280294
fractional number, provided that the radix point character is still
281295
available to use.
282296
283297
=item * $calc->from_base(STRING)
284298
285299
Converts a string representing a number in the associated base to a
286-
Perl number. Unlike versions prior to v1.2, C<from_base()> will fatally
300+
Perl number. Unlike versions prior to v1.20, C<from_base()> will fatally
287301
die if given a character not in $calc's digit set. Hence, if this is a
288302
problem, you should clean your strings (including whitespace) prior to
289303
conversion.
@@ -293,7 +307,7 @@ that the radix point character is still available to use. Negative
293307
strings are supported, provided that the negative character is still
294308
available to use.
295309
296-
Large numbers are also fully supported, as of v1.2. The exact type of
310+
Large numbers are also fully supported, as of v1.20. The exact type of
297311
scalar returned depends on the size of the number. If Perl cannot safely
298312
represent the exact number, a string scalar is returned instead. Note that
299313
C<from_base()> will never return an object, such as a Math::BigInt object,

t/02_digit_dash_dot.t

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,22 @@ push(@calcs, new_ok( $class => [ digits=>[ '0', '.' ], neg_char => '~', radix_ch
1818
my $bignum = Math::BigFloat->new('999999999999999999999999');
1919

2020
for my $calcX ( @calcs ) {
21-
for my $s ($bignum->bneg(), -20..20, $bignum) {
21+
for my $s ($bignum->copy()->bneg(), -20..20, $bignum) {
2222
my $source = $s / 2;
2323
my $in_base_X = $calcX->to_base( $source );
2424
my $in_base_10 = $calcX->from_base( $in_base_X );
2525

2626
# expected result may have changed based on lack of neg/radix
2727
my $expect = $source;
28-
$expect = abs($expect) unless ($calcX->{neg_char});
29-
$expect = int($expect) unless ($calcX->{radix_char});
28+
$expect =~ s/^-// unless ($calcX->{neg_char});
29+
$expect =~ s/\.\d+$// unless ($calcX->{radix_char});
3030

3131
# fix unnecessary zeros
3232
$expect =~ s/0+$// if ($expect =~ /\./);
3333
$expect =~ s/\.$//; # float to whole number
3434

35+
$expect = '0' if $expect eq '-0';
36+
3537
is $in_base_10, $expect, "from( to ( $source ) == $in_base_X ) --> $expect (using ".join(',', $calcX->digits).")";
3638
}
3739
}

0 commit comments

Comments
 (0)