Re: Smooth numeric upgrades?
Darren Duncan wrote: 4.5207196*10**30 -> 45207196*10**37 Before anyone nitpicks, I meant to say on that line: 4.5207196*10**44 -> 45207196*10**37 -- Darren Duncan
Re: [svn:perl6-synopsis] r14585 - doc/trunk/design/syn
On Wednesday, 1. October 2008 21:54:12 [EMAIL PROTECTED] wrote: > If you apply an assignment operator to a protoobject, it is assumed that > you are implementing some kind of notional "reduction" to an accumulator > -variable. To that end, the base operator is dropped and a simple > -assignment is done instead. Hence you may correctly write: > +variable. To that end, the operation is defined in terms > +of the corresponding reduction operator, where the protoobject > +becomes the operator's identify value. So if you say: > + > +$x -= 1; > + > +it is more or less equivalent to: > + > +$x = [-]() unless defined $x;# 0 for [-]() > +$x = $x - 1; > + > +and $x ends up with -1 in it, as expected. Can't we have that as a general feature of all operators? That is: my ($x, $y); say $x * $y; # prints 1 say $x + $y; # prints 0 It is a cleaver idea to make the operator choose an appropriate value for a Nothing value. Why having that only for meta operators? Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smooth numeric upgrades?
Darren Duncan wrote: > Patrick R. Michaud wrote: >> Correct. I suspect that eventually the Rakudo developers will have >> to develop a custom set of PMCs for Perl 6 behaviors rather than >> relying on the Parrot ones. > > I think it would be better for things like unlimited-precision integers > and rationals to be Parrot generic PMCs rather than Perl 6 specific > ones, since there are other languages that also have unlimited-precision > numbers (for example Python afaik) and it would be better to have a > common implementation. Several popular languages have unlimiteds now, > and more are coming over time. +1 The basics of sane numbers should be pushed down into Parrot. (Of course, my vote counts for bupkis as I'm not going to be the one to implement it) -- Whip me, beat me, make my code compatible with VMS!
Re: [svn:perl6-synopsis] r14585 - doc/trunk/design/syn
TSa (Thomas Sandlaß) wrote: > Can't we have that as a general feature of all operators? > That is: > >my ($x, $y); > >say $x * $y; # prints 1 >say $x + $y; # prints 0 > > It is a cleaver idea to make the operator choose an appropriate > value for a Nothing value. Why having that only for meta operators? Because it throws out the utility of the undefined value warning as a way to catch mistakes. Why special case increment and decrement? Two reasons IMO. Incrementing has a very narrow use case and it's pretty hard to screw up. Second is that it's really annoying if you don't. Try working in Javascript which doesn't. You find yourself doing "input ||= 0" a lot... except oh wait you can't do that because ||= doesn't work on undef in Javascript. This is the best I've come up with. [1] [2] input = (input || 0); Point is, certain = quietly treating undef as 0 avoids yucky constructs to appease fussy compilers. The rest, leave alone so the undef warning can do its job. [1] I am not a Javascript programmer, but I haven't seen anything better. [2] Nevermind there's not a proper defined check in there. That would be input = input === null ? input : 0; but most languages don't have a built in dor operator so we won't penalize Javascript for that. -- 185. My name is not a killing word. -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army http://skippyslist.com/list/
Re: Smooth numeric upgrades?
HaloO, On Sunday, 5. October 2008 04:23:42 Darren Duncan wrote: > Note that just as integers are naturally radix independent, the unlimited > rationals should be too, and the latter can compactly represent all > rationals as a triple of integers corresponding roughly to a (normalized) > [mantissa, radix, exponent] triple; with that approach you also get > unlimited floats for free, so no reason to make floats an exception where > they aren't unlimited where integers and other rationals are; after all, > what is a float or scientific notation than just another notation for a > rational value literal. I want to stress this last point. We have the three types Int, Rat and Num. What exactly is the purpose of Num? The IEEE formats will be handled by num64 and the like. Is it just there for holding properties? Or does it do some more advanced numeric stuff? Another matter is how to represent irrationals. With IEEE floats which are basically non-uniformly spaced integers imprecession is involved anyway. But sqrt(2) is a ratio of two infinite integers. How is that handled? Here I see a way for Num to shine as a type that also involves lazy approximations. But then we need a way for the programmer to specify how these approximations shall be handled. Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smooth numeric upgrades?
On Sunday, 5. October 2008 04:23:42 Darren Duncan wrote: > Note that just as integers are naturally radix independent, the unlimited > rationals should be too, and the latter can compactly represent all > rationals as a triple of integers corresponding roughly to a (normalized) > [mantissa, radix, exponent] triple; with that approach you also get > unlimited floats for free, so no reason to make floats an exception where > they aren't unlimited where integers and other rationals are; after all, > what is a float or scientific notation than just another notation for a > rational value literal. > At 18:06 +0200 10/5/08, TSa (Thomas Sandlaß) wrote: >I want to stress this last point. We have the three types Int, Rat and Num. >What exactly is the purpose of Num? The IEEE formats will be handled >by num64 and the like. Is it just there for holding properties? Or does >it do some more advanced numeric stuff? > >Another matter is how to represent irrationals. With IEEE floats which are >basically non-uniformly spaced integers imprecession is involved anyway. >But sqrt(2) is a ratio of two infinite integers. How is that handled? Here >I see a way for Num to shine as a type that also involves lazy approximations. >But then we need a way for the programmer to specify how these approximations >shall be handled. I'm not so sure that sophisticated numbering is necessary for a practical extraction and report language. But. . . Symbolic algebra packages handle irrationals like sqrt(2) with a "root of" function which can be included in a result before it is deliberately converted to an approximation in a later step. Perl should NOT do things like that. As for unlimited precision in floats I'd rather see a floating point number triple that includes, in its structure, an estimate of error, and physical units. Multiplying amperes by volts would then return watts with an appropriately calculated estimate of the error. Testing for zero would include the error estimate. When I work with data from the power company expressed in MMBTU I can add to a working table of units that MMBTU translates to 10^6 BTU because the M means 1000 as in millia pasuum. I could also provide a conversion from BTU to joules and have it properly handled. Many arithmetic errors are the result of not keeping the units inside of the evaluation. The result is newspaper articles that confuse energy and power as they extract from data provided by power company engineers. "1 kW per day" is meaningless. I wonder if they use perl to extract the data. And what are those two infinite integers? I wonder if there is a series that expresses each one? -- --> A fair tax is one that you pay but I don't <--
Re: Smooth numeric upgrades?
TSa (Thomas Sandlaß) wrote: > I want to stress this last point. We have the three types Int, Rat and Num. > What exactly is the purpose of Num? The IEEE formats will be handled > by num64 and the like. Is it just there for holding properties? Or does > it do some more advanced numeric stuff? "Int", "Rat" [1] and "Num" are all human types. They work like humans were taught numbers work in math class. They have no size limits. They shouldn't lose accuracy. [2] As soon as you imply that numbers have a size limit or lose accuracy you are thinking like a computer. That's why "num64" is not a replacement for "Num", conceptually nor is "int64" a replacement for "Int". They have limits and lose accuracy. Making "Num" just work like humans expect is the "more advanced numeric stuff" I suppose. :) [1] As a name "Rat" as the type which holds fractions is about as good as "Float" to be the type which holds decimal numbers. Gotta be something that makes more sense to non CS people. Like, say, "Fraction". [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. -- 184. When operating a military vehicle I may *not* attempt something "I saw in a cartoon". -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army http://skippyslist.com/list/
Re: Smooth numeric upgrades?
On Sat, Oct 04, 2008 at 09:37:29PM -0700, Mark Biggar wrote: > trivial and vice versa. But promotion (or demotion) between IEEE floats > and rationals is really hard and I don't know of a language that even > tries. The major problem is that the demotion from rational to IEEE > float is very lossy. In general, there are many possible distinct > rationals that convert into the same IEEE value and converting IEEE > float to the simplest rational out of that set is a very expensive > operation.. Once you're in rationals you probably never want to demote And I can't see why it's anything other than a heuristic. For example, 0.2 is an infinite binary fraction. So store that as an IEEE float (heck, in any form of float with a binary mantissa of fixed precision) and 1/5 isn't the *only* rational that could have got you there. Something like 0b00011001100110011001100110011001100110011001100110011 / 0b1 (900719925474099 / 4503599627370496) would also result in the same bit pattern in the mantissa. How does the implementation tell which rational the floating point value actually came from > back to IEEE (except possibly at the very end). Every language that > supports rationals, that I know of, leaves it up to the programmer to > decide whether they will be doing computations in IEEE float or > rationals and do not try to automatically convert back and forth. I > looked at thos and basically gave up when I was writing the perl 5 > Bigint and Bigrat packages. > > Before you discuss implementations, you should define exactly what rules > you are going to use for promotion and demotion between the various types. Studiously ignoring that request to nail down promotion and demotion, I'm going to jump straight to implementation, and ask: If one has floating point in the mix [and however much one uses rationals, and has the parser store all decimal string constants as rationals, floating point enters the mix as soon as someone wants to use transcendental functions such as sin(), exp() or sqrt()], I can't see how any implementation that wants to preserve "infinite" precision for as long as possible is going to work, apart from storing every value as a thunk that holds the sequence of operations that were used to compute the value, and defer calculation for as long as possible. (And possibly as a sop to efficiency, cache the floating point outcome of evaluating the thunk if it gets called) Nicholas Clark
[svn:perl6-synopsis] r14586 - doc/trunk/design/syn
Author: larry Date: Sun Oct 5 17:05:41 2008 New Revision: 14586 Modified: doc/trunk/design/syn/S03.pod Log: Add missing series operator, mostly for readability. Modified: doc/trunk/design/syn/S03.pod == --- doc/trunk/design/syn/S03.pod(original) +++ doc/trunk/design/syn/S03.podSun Oct 5 17:05:41 2008 @@ -12,9 +12,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 8 Mar 2004 - Last Modified: 1 Oct 2008 + Last Modified: 5 Oct 2008 Number: 3 - Version: 140 + Version: 141 =head1 Overview @@ -49,7 +49,7 @@ R Item assignment = := ::= => += -= **= xx= .= L Loose unary true not X Comma operator, p5=> -X List infixZ minmax X X~X X*X XeqvX +X List infixZ minmax X X~X X*X XeqvX ... R List prefix : print push say die map substr ... [+] [*] any $ @ X Loose and and andthen X Loose or or xor orelse @@ -1584,6 +1584,75 @@ See L. +=item * + +C<< infix:<...> >>, the series operator. + +This operator takes a concrete list on its left and a function to be +iterated on its right when the list must be extended. + +The value of the operator is the lazy list formed of the +concrete list followed by the result of applying the function to the +tail of the list as needed. The function indicates by its arity +how many of the preceding values to pay attention to (and which the +operator must track internally). Demonstration of this falls to the +lot of the venerable Fibonacci sequence: + +1, 1 ... { $^y + $^z } # 1,1,2,3,5,8... +1, 1 ... &infix:<+># 1,1,2,3,5,8... + +More typically the function is unary, in which case any extra values +in the list may be construed as human-readable documentation: + +0,2,4 ... { $_ + 2 } # same as 1..*:by(2) + ... { .succ } # same as 'a'..* + +The function need not be monotonic, of course: + +1 ... { -$_ } # 1, -1, 1, -1, 1, -1... +False ... &prefix: # False, True, False... + +The function can be 0-ary as well: + +() ... &rand # list of random numbers + +If the right operand is C<*> (Whatever) and the sequence is obviously +arithmetic or geometric, the appropriate function is deduced: + +1, 3, 5 ... * # odd numbers +1. 2. 4 ... * # powers of 2 + +Conjecture: other such patterns may be recognized in the future, +depending on which unrealistic benchmark we want to run faster. C<:)> + +Note: the yada operator is recognized only where a term is expected. +This operator may only be used where an infix is expected. If you +put a comma before the C<...> it will be taken as a yada list operator +expressing the desire to fail when the list reaches that point: + +1..20, ... "I only know up to 20 so far mister" + +If the yada operator finds a closure for its argument at compile time, +it should probably whine about the fact that it's difficult to turn +a closure into an error message. Alternately, we could treat +an elipsis as special when it follows a comma to better support +traditional math notation. + +The function may choose to terminate its list by returning (). +Since this operator is list associative, an inner function may be +followed by a C<...> and another function to continue the list, +and so on. Hence, + +1 ... { $_ + 1 if $_ < 10 } + ... { $_ + 10 if $_ < 100 } + ... { $_ + 100 if $_ < 1000 } + +produces + +1,2,3,4,5,6,7,8,9, +10,20,30,40,50,60,70,80,90, +100,200,300,400,500,600,700,800,900 + =back Many of these operators return a list of Captures, which depending on
Re: Smooth numeric upgrades?
In-Reply-To: Message from Nicholas Clark <[EMAIL PROTECTED]> of "Sun, 05 Oct 2008 22:13:14 BST." <[EMAIL PROTECTED]> > Studiously ignoring that request to nail down promotion and demotion, I'm > going to jump straight to implementation, and ask: > If one has floating point in the mix [and however much one uses rationals, > and has the parser store all decimal string constants as rationals, floating > point enters the mix as soon as someone wants to use transcendental functions > such as sin(), exp() or sqrt()], I can't see how any implementation that wants > to preserve "infinite" precision for as long as possible is going to work, > apart from >storing every value as a thunk that holds the sequence of operations that >were used to compute the value, and defer calculation for as long as >possible. (And possibly as a sop to efficiency, cache the floating point >outcome of evaluating the thunk if it gets called) >Nicholas Clark My dear Nicholas, You mentioned sin(), exp(), and sqrt() as being "transcendental" functions, but this is not true! Perhaps you meant something more in the way of their being--um, "irrational". but far be it from me to risk using so loaded a word in reference to anyone's hypothetical intentions or rationale! :-) While all transcendentals are indeed irrationals, the opposite relationship does *not* apply. It's all really rather simple, provided you look at it as a brief, binary decision-tree. => All reals are also one of either rational or irrational: + Rational numbers are those expressible as the RATIO of I/J, where I is any integer and J any non-zero integer. - Irrationals are all other reals *EXCEPT* the rationals. => All irrationals are also one of either algebraic or transcendental: + Algebraic numbers are solutions to polynomial equations of a single variable and integer coefficients. When you solve for x in the polynomial equation 3*x**2 - 15 == 0, you get an algebraic number. - Transcendentals are all other irrationals *EXCEPT* the algebraics. Thinking of the sine function and its inverse, I notice that sin(pi/2) == 1 and asin(1) is pi/2. Pi is *the* most famous of transcendental numbers, and sin() is a transcendental function. Thinking of the exponential function and its inverse, I notice that exp(1) == e and log(e) == 1. And e, "Euler's number", is likely the #2 most famous transcendental, and exp() is a transcendental function. However, we come now to a problem. If you solved the simple equation I presented above as one whose solution was by definition *not* a transcendental but rather an algebraic number, you may have noticed that solution is 5**(1/2), better known as sqrt(5). So that makes sqrt(5) an algebraic number, and sqrt() is an algebraic function, which means therefore that it is *not* a transcendental one. Q.E.D. :-) Ok, I was teasing a little. But I'd now like to politely and sincerely inquire into your assertion that floating point need inevitably enter the picture just to determine sin(x), exp(x), or sqrt(x). Your last one, sqrt(), isn't hard at all. Though I no longer recall the algorithm, there exists one for solving square roots by hand that is only a little more complicated than that of solving "long division" by hand. Like division, it is an iterative process, somewhat tedious but quite well-defined easily implemented even on pen and paper. Perhaps that has something to do with sqrt() being an algebraic function. :-) j/k As for the two transcendental functions, this does ask for more work. But it's not as though we do not understand them, nor how to derive them at need from first principles! They aren't magic black-ball functions with secret look-up tables that when poked with a given input, return some arbitrary answer. We *know* how to *do* these! Sure, many and probably most solutions, at least for the transendentals, do involve power series, and usually Taylor Series. But this only means that you get to joyfully sum up an infinite sequence of figures receding into infinity ("And beyond!" quoth Buzz), but where each figure in said series tends to be a reasonably simple and straightforward computation. For example, each term in the Taylor Series for exp(x) is simply x**N / N!, and the final answer the sum of all suchterms for N going from 0 to infinity. Its series is therefore x**0 / 0! # er: that's just 1, of course :-) + x**1 / 1! + x**2 / 2! + x**3 / 3! + x**4 / 4! + + + + + + + + + + + ad infinitum. For sin(x), it's a bit harder, but not much: the series is a convergent one of alternating sign, running N from 0 to infinity and producing a series that looks like this: (x**1 / 1!)# er: that's just x, of course :-) - (x**3 / 3!) + (x**5 / 5!) - (x**7 / 7!) + (x**9 / 9!) - + - + - + - + - + ad infinitum. Each term in the sin(x) series is still a comparitively easy one, reading much better on pap
Re: [svn:perl6-synopsis] r14586 - doc/trunk/design/syn
On Sun, 2008-10-05 at 17:05 -0700, [EMAIL PROTECTED] wrote: > +C<< infix:<...> >>, the series operator. Lovely, just lovely. > +1, 3, 5 ... *# odd numbers > +1. 2. 4 ... *# powers of 2 Did you mean to use commas on that second line? -'f
[svn:perl6-synopsis] r14587 - doc/trunk/design/syn
Author: larry Date: Sun Oct 5 19:14:11 2008 New Revision: 14587 Modified: doc/trunk/design/syn/S03.pod Log: typos Modified: doc/trunk/design/syn/S03.pod == --- doc/trunk/design/syn/S03.pod(original) +++ doc/trunk/design/syn/S03.podSun Oct 5 19:14:11 2008 @@ -1620,7 +1620,7 @@ arithmetic or geometric, the appropriate function is deduced: 1, 3, 5 ... * # odd numbers -1. 2. 4 ... * # powers of 2 +1, 2, 4 ... * # powers of 2 Conjecture: other such patterns may be recognized in the future, depending on which unrealistic benchmark we want to run faster. C<:)> @@ -1635,7 +1635,7 @@ If the yada operator finds a closure for its argument at compile time, it should probably whine about the fact that it's difficult to turn a closure into an error message. Alternately, we could treat -an elipsis as special when it follows a comma to better support +an ellipsis as special when it follows a comma to better support traditional math notation. The function may choose to terminate its list by returning ().
Re: [svn:perl6-synopsis] r14586 - doc/trunk/design/syn
On Mon, Oct 06, 2008 at 09:16:27AM +0800, Xiao Yafeng wrote: : + : > +The function may choose to terminate its list by returning (). : > +Since this operator is list associative, an inner function may be : > +followed by a C<...> and another function to continue the list, : > +and so on. Hence, : > + : > +1 ... { $_ + 1 if $_ < 10 } : > + ... { $_ + 10 if $_ < 100 } : > + ... { $_ + 100 if $_ < 1000 } : > + : > +produces : > + : > +1,2,3,4,5,6,7,8,9, : > +10,20,30,40,50,60,70,80,90, : > +100,200,300,400,500,600,700,800,900 : > + : > =back : : : curious whether I can say: : 1... {$_ + 1 if @_.elems <10} : : 1,2,3,4,5,6,7,8,9, Good question. I think it ought to be okay, though it basically forces the operator to keep track of the entire array in order to pass it in as a slurpy on every iteration. But it seems like *-ary args should be allowed as an extreme case. Here's the same thing more explicitly, expressed in unary form: @seq := 1 ... { $_ + 1 if @seq < 10 } The thing is, the operator will still have to keep track of all the values even if the list has already given away some of those value via an iterator. Here's a cute variant that doesn't have to store all the values just to keep count: 1 ... { $_ + 1 if ++(state $) < 10 } Hmm, I think *my* state's $ will soon be less than 10, at the rate they're spending... :) Larry
Re: [svn:perl6-synopsis] r14586 - doc/trunk/design/syn
On Sun, Oct 05, 2008 at 07:31:30PM -0700, Larry Wall wrote: : @seq := 1 ... { $_ + 1 if @seq < 10 } Actually, that one might not work, since we can't find the length of @seq without knowing how many value the closure will generate. The implicit version would not have that problem. Larry
Re: [svn:perl6-synopsis] r14586 - doc/trunk/design/syn
<[EMAIL PROTECTED]> wrote: > Log: > Add missing series operator, mostly for readability. Is there a way for the continuing function to access its index as well as, or instead of, the values of one or more preceding terms? And/or to access elements by counting forward from the start rather than backward from the end? There is a mathematical technique whereby any series that takes the form of "F(n) = A*F(n-1) + B*F(n-2) + C*F(n-3)" can be reformulated as a function of n, A, B, C, F(0), F(1), and F(2). (And it is not limited to three terms; it can be as few as one or as many as n-1 - although it has to be the same number for every calculated term in the series.) For the Fibonacci series, it's something like: F(n) = (pow((sqrt(5) + 1)/2, n) + pow((sqrt(5) - 1)/2, n))/sqrt(5) ...or something to that effect. It would be nice if the programmer were given the tools to do this sort of thing explicitly instead of having to rely on the optimizer to know how to do this implicitly. -- Jonathan "Dataweaver" Lang
Re: Smooth numeric upgrades?
Doug McNutt wrote: At 18:06 +0200 10/5/08, TSa (Thomas Sandlaß) wrote: Another matter is how to represent irrationals. With IEEE floats which are basically non-uniformly spaced integers imprecession is involved anyway. But sqrt(2) is a ratio of two infinite integers. How is that handled? I would not consider an irrational to be a ratio of anything; rather it is a number that can't be expressed as a ratio of 2 integers. Symbolic algebra packages handle irrationals like sqrt(2) with a "root of" function which can be included in a result before it is deliberately converted to an approximation in a later step. Perl should NOT do things like that. Whether or not Perl has built-in support for symbolic math, something which incidentally some other general purpose languages do have afaik, any Perl representations of exact irrational numbers definitely should be symbolic in nature, that is an irrational number value is simply defined by a formula involving operators and rational literals, and any type implementing this would be neither the Int nor Rat type. As for unlimited precision in floats I'd rather see a floating point number triple that includes, in its structure, an estimate of error, and physical units. I see that you can have both unlimited precision rationals (which is what floats are) that also know the error estimate and physical units; they would be defined in terms of an exact precision rational plus the estimate and units as additional attributes or metadata. -- Darren Duncan
Re: [svn:perl6-synopsis] r14586 - doc/trunk/design/syn
On Sun, Oct 05, 2008 at 08:19:42PM -0700, Jon Lang wrote: : <[EMAIL PROTECTED]> wrote: : > Log: : > Add missing series operator, mostly for readability. : : Is there a way for the continuing function to access its index as well : as, or instead of, the values of one or more preceding terms? And/or : to access elements by counting forward from the start rather than : backward from the end? That's what the other message was about. @_ represents the entire list generated so far, so you can look at its length or index it from the begining. Not guaranteed to be as efficient though. : There is a mathematical technique whereby any series that takes the : form of "F(n) = A*F(n-1) + B*F(n-2) + C*F(n-3)" can be reformulated as : a function of n, A, B, C, F(0), F(1), and F(2). (And it is not : limited to three terms; it can be as few as one or as many as n-1 - : although it has to be the same number for every calculated term in the : series.) For the Fibonacci series, it's something like: : : F(n) = (pow((sqrt(5) + 1)/2, n) + pow((sqrt(5) - 1)/2, n))/sqrt(5) : : ...or something to that effect. It would be nice if the programmer : were given the tools to do this sort of thing explicitly instead of : having to rely on the optimizer to know how to do this implicitly. Um, I don't understand what you're asking for. Explicit solutions are always available... Larry
Re: Smooth numeric upgrades?
Michael G Schwern wrote: TSa (Thomas Sandlaß) wrote: I want to stress this last point. We have the three types Int, Rat and Num. What exactly is the purpose of Num? The IEEE formats will be handled by num64 and the like. Is it just there for holding properties? Or does it do some more advanced numeric stuff? "Int", "Rat" [1] and "Num" are all human types. They work like humans were taught numbers work in math class. They have no size limits. They shouldn't lose accuracy. [2] As soon as you imply that numbers have a size limit or lose accuracy you are thinking like a computer. That's why "num64" is not a replacement for "Num", conceptually nor is "int64" a replacement for "Int". They have limits and lose accuracy. All agreed. [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. For starters, any "limit" built into a type definition should be defined not as stated above but rather with a simple subtype declaration, eg "subtype of Rat where ..." that tests for example that the Rat is an exact multiple of 1/1000. Second, any truncation should be done at the operator level not at the type level; for example, the rational division operator could have an optional extra argument that says the result must be rounded to be an exact multiple of 1/1000; without the extra argument, the division doesn't truncate anything. 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. 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. 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. Come to think of it, isn't "whatever" how Num is already defined? If so I think that is clearly distinct from Rat. -- Darren Duncan
Re: Smooth numeric upgrades?
Nicholas Clark wrote: If one has floating point in the mix [and however much one uses rationals, and has the parser store all decimal string constants as rationals, floating point enters the mix as soon as someone wants to use transcendental functions such as sin(), exp() or sqrt()], I can't see how any implementation that wants to preserve "infinite" precision for as long as possible is going to work, apart from storing every value as a thunk that holds the sequence of operations that were used to compute the value, and defer calculation for as long as possible. (And possibly as a sop to efficiency, cache the floating point outcome of evaluating the thunk if it gets called) Floating point has no effect on this. A float is just a syntax for an exact rational. What you're talking about mostly is how an exact irrational would be represented, symbolically. The result of an exact numeric sin() etc would be a symbolic number, and it is only when you separately explicitly convert it to a rational does any rounding and loss occur, and it would be the rounding operation itself that has extra parameters to control the rounding. Alternately, an inexact numeric sin() that results in an exact rational is just a wrapper over the last 2 operations combined, and it takes rounding-control parameters. I see no problem here. -- Darren Duncan
Re: Smooth numeric upgrades?
So, the concrete use-case I'm thinking of here is currency. 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. > > For starters, any "limit" built into a type definition should be defined > not as stated above but rather with a simple subtype declaration, eg > "subtype of Rat where ..." that tests for example that the Rat is an > exact multiple of 1/1000. > > Second, any truncation should be done at the operator level not at the > type level; for example, the rational division operator could have an > optional extra argument that says the result must be rounded to be an > exact multiple of 1/1000; without the extra argument, the division > doesn't truncate anything. > > 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. But sometimes I want to hang onto fractional pennies and use them in calculation, just hide them from view. And sometimes I don't. > 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. -- 44. I am not the atheist chaplain. -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army http://skippyslist.com/list/