New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support arbitrary-precision numbers #241
Comments
This is an interesting idea but probably infeasible. IMHO, it is not justifiable from a value versus complexity viewpoint. Functions like My opinion is support for arbitrary precision numbers is useful it has no place in a shell like Elvish. The Elvish community is better served by introducing idioms for "close enough" equality matching of values; e.g., |
Before getting too much into Go-specific technical difficulties, let's take a step back and start from the design. Several languages have both arbitrary-precision numbers and finite-precision numbers, and their designers have thought out the question. Follow one the established designs, and it's a matter of figuring out how to map that to Go's
|
Elvish does not restrict itself to the traditional notion of shells: https://elv.sh/ref/philosophy.html#the-language. We can chat more on IM about the philosophy if you like.
I am not aware of programming languages that do that, so I'd be very cautious about it. Most languages simply leave this problem unsolved, and expect programmers to know that floating point numbers are not precise. |
The problem is that the vast majority of shell users, who are not programmers in the sense you mean, are not cognizant of this issue. It seems to me the question boils down to whether Elvish is meant to be useful for problems where the programmer wants to be 100% in control of floating point comparisons or produces reasonable results for the 99.999% of shell users. Given the inherent tension in a shell language such as Elvish (consider the implicit string <=> float64 conversions) it seems to me that providing reasonable behavior is preferable to providing the illusion of complete control. |
Note that my concerns about "close enough" floating point equality does not imply Elvish should not, or can not, support other representations such as arbitrarily large integers or rational numbers. |
Everyone interested in this topic should watch Rob Pike's presentation about an APL like calculator that supports "bignums": https://www.youtube.com/watch?v=PXoG0WX0r_E |
It is my design philosophy that user-friendly features must be built on top of a sound language core, not compromise it.
|
https://github.com/shopspring/decimal might provide a basis for resolving this issue. |
@krader1961 thanks, but that's for fixed-point decimal number; Go's builtin math/big package is perhaps a better starting point. |
Oh, I guess you suggested the library since it provides more mathematical functions than math/big. But a decimal arbitrary-precision number library is not really what Elvish needs. I'll just start with whatever math/big supports; so applying |
The Racket reference doesn't actually have a lot of details on how numbers are actually implemented; the Chez Scheme User Guide is much clearer on that. Ignoring complex numbers, there are just 4 types, each with a corresponding type in Go:
Raku's model is essentially the same, with two key differences:
This means that with Raku, you get accurate results when the computation is not too expensive, but as soon as it gets expensive the results become approximates. Practical design choices, but I prefer Scheme's model, where exact numbers can only degrade either when explicitly converted or when used in a function that doesn't support exact numbers. |
This approach is my biggest concern with this proposal. In a language like Go the type mismatch can be detected at compile time. In a language like Elvish the error will occur at run time. However, you then stated "... degrade either when explicitly converted or when used in a function that doesn't support exact numbers." Which implies that passing a bignum to a function like |
Right, my preference change a bit on this one. Math functions that do not support big numbers should convert their arguments to float64.
Seems you answered your own question here. :) |
The conclusion I came to is probably correct for most of the math commands but I feel it's always important to explore alternative approaches. For example, consider commands like |
Hmm, so when you said "lowest common denominator" you meant always returning floats. That's not what I have in mind; the idea is to return the "lowest common denominator" in relation to the arguments. So Again, Scheme already has the model for this, so I consider this more or less a solved problem, although I should expand a bit more on the Scheme model. To start with, Scheme's model only distinguishes two types of numbers: exact and inexact numbers. In most implementations, the former includes fixnum, bignum and ratnum. The latter includes flonum. Exact numbers can be promoted losslessly, and "demoted" when needed, but this is an implementation detail that most users do not need to worry about. Chez Scheme for example always normalizes exact numbers to the smallest representation that can hold them. The rest of the model involves functions:
And that's mostly it. There are a handful of exceptions of when you can get an exact result even when some of arguments are inexact or the function is normally not exactness-preserving. Most such exceptions are when one of the arguments is an exact 0. For example, multiplying an exact 0 with an exact number produces an exact 0, and the sine of an exact 0 is an exact 0. |
(Corrected the last paragraph on the exception to the rule.) |
That math functions are classified as exactness preserving or not is something I hadn't grasped from the quick skim of the Scheme doc you linked to earlier. That clarifies the model you have in mind and basically aligns with what I was implying with my previous comment. I'm still curious whether something like |
Upsides:
+ 0.1 0.2
is 0.3, instead of 0.30000000000000004Downsides:
float64
;The text was updated successfully, but these errors were encountered: