On Mon, 06 Oct 2008 at wee small hour of 02:20:22 EDT
you, Michael G Schwern <[EMAIL PROTECTED]>, wrote:
> Darren Duncan wrote:
>>> [2] "Num" should have an optional limit on the number of
>>> decimal places it remembers, like NUMERIC in SQL, but
>>> that's a simple truncation.
>> I disagree.
>> Any numeric operations that would return an irrational number
>> in the general case, such as sqrt() and sin(), and the user
>> desires the result to be truncated to an exact rational number
>> rather than as a symbolic number, then those operators should
>> have an extra argument that specifies rounding, eg to an exact
>> multiple of 1/1000.
> That seems like scattering a lot of redundant extra arguments
> around. The nice thing about doing it as part of the type is
> you just specify it once.
> But instead of truncating data in the type, maybe what I want
> is to leave the full accuracy inside and instead override
> string/numification to display only 2 decimal places.
This is currently something of an annoyance with Math::Complex.
It needs a way of specify epsilon.
If you ask for both sqrt()s of 4, you get
(2, -2+2.44929359829471e-16i)
in Cartesian but in Polar:
( [2,0], [2,pi] )
Is the problem that it's working in Polar and the conversion to
Cartesian is off by a wee bit? I would really like to get
Cartesian answers of (2, -2), not that -2e-16i silliness.
If you ask for both roots of -4, you get
Cartesian:
( 1.22464679914735e-16+2i, -3.67394039744206e-16-2i )
Polar:
( [2,pi/2], [2,-1pi/2] );
But I'd like a Cartesian return of (2i, -2i).
And a Polar return of ([2,pi/2],[2,-pi/2]).
It's worse still with the 10 roots of 2**10:
The 10 roots of 1024 are:
CRTSN: 1: 2
POLAR: 1: [2,0]
CRTSN: 2: 1.61803398874989+1.17557050458495i
POLAR: 2: [2,pi/5]
CRTSN: 3: 0.618033988749895+1.90211303259031i
POLAR: 3: [2,2pi/5]
CRTSN: 4: -0.618033988749895+1.90211303259031i
POLAR: 4: [2,3pi/5]
CRTSN: 5: -1.61803398874989+1.17557050458495i
POLAR: 5: [2,4pi/5]
CRTSN: 6: -2+2.44929359829471e-16i
POLAR: 6: [2,pi]
CRTSN: 7: -1.61803398874989-1.17557050458495i
POLAR: 7: [2,-4pi/5]
CRTSN: 8: -0.618033988749895-1.90211303259031i
POLAR: 8: [2,-3pi/5]
CRTSN: 9: 0.618033988749894-1.90211303259031i
POLAR: 9: [2,-2pi/5]
CRTSN: 10: 1.61803398874989-1.17557050458495i
POLAR: 10: [2,-1pi/5]
The 10 roots of -1024 are:
CRTSN: 1: 1.90211303259031+0.618033988749895i
POLAR: 1: [2,0.314159265358979]
CRTSN: 2: 1.17557050458495+1.61803398874989i
POLAR: 2: [2,0.942477796076938]
CRTSN: 3: 1.22464679914735e-16+2i
POLAR: 3: [2,pi/2]
CRTSN: 4: -1.17557050458495+1.61803398874989i
POLAR: 4: [2,2.19911485751286]
CRTSN: 5: -1.90211303259031+0.618033988749895i
POLAR: 5: [2,2.82743338823081]
CRTSN: 6: -1.90211303259031-0.618033988749895i
POLAR: 6: [2,-2.82743338823081]
CRTSN: 7: -1.17557050458495-1.61803398874989i
POLAR: 7: [2,-2.19911485751286]
CRTSN: 8: -3.67394039744206e-16-2i
POLAR: 8: [2,-1pi/2]
CRTSN: 9: 1.17557050458495-1.6180339887499i
POLAR: 9: [2,-0.942477796076938]
CRTSN: 10: 1.90211303259031-0.618033988749895i
POLAR: 10: [2,-0.31415926535898]
>> Note, a generic numeric rounding operator would also take the
>> "exact multiple of" argument rather than a "number of digits"
>> argument, except when that operator is simply rounding to an
>> integer, in which case no such argument is applicable.
>> Note, for extra determinism and flexibility, any operation
>> rounding/truncating to a rational would also take an optional
>> argument specifying the rounding method, eg so users can
>> choose between the likes of half-up, to-even, to-zero, etc.
>> Then Perl can easily copy any semantics a user desires,
>> including when code is ported from other languages and wants
>> to maintain exact semantics.
> Yes, this is very important for currency operations.
>> Now, as I see it, if "Num" has any purpose apart from "Rat",
>> it would be like a "whatever" numeric type or effectively a
>> union of the Int|Rat|that-symbolic-number-type|etc types, for
>> people that just want to accept numbers from somewhere and
>> don't care about the exact semantics. The actual underlying
>> type used in any given situation would determine the exact
>> semantics. So Int and Rat would be exact and unlimited
>> precision, and maybe Symbolic or IRat or something would be
>> the symbolic number type, also with exact precision
>> components.
> That sounds right. It's the "whatever can conceivably be
> called a number" type.
I think you might be surprised by what some people conceive
of by numbers. :-(
--tom
#!/usr/bin/perl
use strict;
use warnings;
use Math::Complex;
my $STYLE = "NORMAL";
# my $STYLE = "HACKED";
unless (@ARGV) {
die "usage: $0 number rootcount\n";
}
my ($number, $rootcount) = @ARGV;
$number = cplx($number);
die "$0: $number poor for rooting\n" if !$number;
die "$0: $rootcount should be positive integer"
if $rootcount && int($rootcount) != $rootcount;
print "The $rootcount roots of $number are:\n";
my @roots = root($number, int($rootcount));
my $width = length @roots;
for (my $idx = 0; $idx < @roots; $idx++) {
my $z = $roots[$idx];
my $r = Re($z);
my $i = Im($z);
if ($STYLE eq "NORMAL") {
printf "CRTSN: %${width}d: %s\n", 1+$idx, $z;
$z->display_format("polar");
printf "POLAR: %${width}d: %s\n", 1+$idx, $z;
next;
}
printf "%${width}d: ", 1+$idx;
if ($r) {
my $s = sprintf "%.6f", $r;
$s =~ s/0+$//;
if ($s =~ s/\.$//) {
# whole RE part
print (($s < 0) ? "-" : " ");
printf "%-7d", abs($s);
} else {
printf "%8g", $s;
}
} else {
}
if ($i) {
my $s = sprintf "%.6f", $i;
$s =~ s/0+$//;
$s =~ s/\.$//;
if ($s ne '0') {
print " " if $s !~ m/\./;
print (($s < 0) ? " -" : "+" );
if ($s !~ m/\./) {
printf "%di", abs($s);
} else {
printf "%7gi", abs($s);
}
}
}
print "\n\n";
}