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";

} 

Reply via email to