Which programming languages have arbitrary precision floating-point literals?
Asked Answered
P

3

6

This question is asking for programming languages which accept numeric constants for assignment to arbitrary precision variables or for use in arbitrary precision expressions without performing conversion to IEEE floating-point representation before assignment or application in an expression. For example, the following pseudo-language assignment expression:

BigNum x = 0.1;

Many languages provide or have access to libraries which will enable construction of such BigNum type objects from a text string. I am looking for programming languages which can convert a numeric token like 0.1 directly into a BigNum without requiring the programmer to create a string which must then be parsed and potentially throw an exception or flag an error at runtime. Instead, I am interested in languages where the compiler or tokenizer can report syntax errors from incorrectly formatted numbers or invalid expressions before processing the numeric literal into an arbitrary precision decimal or integer ratio representation.

From Literals/Floating point on the Rosetta Code web site, it looks like J, Maple, and Maxima provide a literal syntax for arbitrary precision floating point numbers. Do any other more widely used languages provide the same or something similar to the pseudo-example I provided above?

As a concrete example, Julia provides built in support for rational numbers. These number have a literal representation which can be used in source code. For example:

x = 1//10

Now 1//10 and 0.1 are the same numbers mathematically -- in base 10. However, most programming languages will convert a literal decimal number in source code into an IEEE floating-point number. Often that is exactly what is wanted. However, more than a few people unfamiliar with the IEEE floating point representations of numbers -- or similar floating-point representations which have largely faded into history -- are a surprised to learn that one-tenth isn't exactly one-tenth when it is converted into a binary fraction. Moreover, this surprise usually arises after code which works "most of the time" produces a surprising result when floating-point "errors" accumulate rather average/cancel out. Of course, that is the nature of floating-point representations and arithmetic operations which are, just the same, very useful in practice. Caveat emptor: What Every Computer Scientist Should Know About Floating-Point Arithmetic

Still, I find there are times when integers are insufficient and floating-point numbers introduce unnecessary issues in otherwise exact calculations. For that, rational number and arbitrary precision libraries fit the bill. Great. However, I would still like to know if there are any languages which support direct representation of rational and arbitrary precision literals in the language itself. After all, I do not want to use a language which only has string literals which must then be parsed into numbers at run-time.

So far, Julia is a good answer for rational numbers, but far from the only language with support for rational number literals. However, it does not have arbitrary precision literals. For that, J, Maple, and Maxima seem to have what I am seeking. Perhaps that is very nearly the complete list. Still, if anyone knows of another candidate or two, I would appreciate a pointer...

The Answer So Far...

The best answer to date is Haskell. It provides a rich comprehension of numeric types and operations as well as numeric literal notation which includes rational number expressions and which appears to provide for treating decimal numbers with a fractional part as rational numbers rather than floating-point literals in all cases. At least, that is what I gather from a quick reading of Haskell documentation and a blog post I came across, Overloading Haskell numbers, part 3, Fixed Precision, in which the author states:

...notice that what looks like a floating point literal is actually a rational number; one of the very clever decisions in the original Haskell design.

For many programmers, Julia will be more approachable while offering excellent support for a variety of mathematical types and operations as well as usually excellent performance. However, Python has a very capable syntax as well, many natively compiled packages which match or exceed those available to Julia today, and, unquestionably, enjoys far greater adoption and application in commercial, open-source, and academic projects -- still, my personal preference is for Julia if I have a choice.

For myself, I will be spending more time reseaching Haskell and revisiting Ocaml/F# which may be viable intermediate choices between Julia/Python like languages and a language like Haskell -- how those programming languages may fall across some sort of spectrum is left as an exercise for the reader. If Ocaml/F# offer comparable expressive power to Haskell in the cases in which I have an interest, they may be a better choice just on the basis of current and likely future adoption rates. But for now, Haskell seems to be the best answer to my original question.

Pervert answered 15/1, 2014 at 21:27 Comment(17)
Why is this important to you?Unhorse
Most of the software I write involves mathematical computations almost entirely consisting of basic arithmetic operations. Every number the users of my software enter and every literal either in my code or used in a unit test represents a number which is either an integer or a ratio of finite numbers (i.e. a rational number). However, very simple numbers provided by users cannot be exactly represented as an IEEE floating point number even when that may be required for a given input. For example, users must enter a set of fractional numbers which sum to 1.0 for a given model (e.g. .8, .1, .1).Pervert
Because this is about dealing with input from users, you really don't need a language which handles this with literal syntax. You need to parse your input anyway, so you can use it to drive a library in any language. Focus on your other needs to choose a language (including ease of building the necessary parsers).Unhorse
...Of course, I can code around every one of the use cases, but it can be tedious. I am looking for candidate languages to use in future projects -- or a new version of the current project -- in which arithmetic is efficiently supported for operations on rational numbers, including fractions provided in decimal notation. To a large extent, Julia meets my requirements, though it isn't the only reasonable candidate.Pervert
... However, Julia does not have have a concise notation for decimal numbers which the compile should translate into rational numbers or arbitrary precision decimal numbers as the case may be. Instead, like Java and many other languages, a number like 0.1 must either be manually factored into 1//10 for Julia or passed as a string to a function which constructs a number object of the correct type using yet another little parser while the compiler remains ignorant of the string's contents or semantics.Pervert
I honestly doubt you'll find that such languages actually increase the convenience of what you are doing. There's a reason why this mostly exists in languages where the programmer is likely to be entering the numbers themselves, and generally using the code to do their own analysis: that's the only time it makes anything more convenient.Unhorse
@Unhorse Not all users enter numbers as text through a user interface. Most do, but some use an API which falls back to using string literals containing numeric literals which must be parsed at runtime to avoid having 0.1 lose precision by an intermediate conversion to IEEE floating point representation. Granted, this is not a big deal as long as programmers understand the issues with floating point arithmetic. But again, all number literals -- not those which result from a computation or represent irrational constants like pi -- are written in code or in user input as finite rational numbers.Pervert
@Unhorse Of course, your mileage may vary... In any case, I am still interested in any suggestions from people who know of languages with built-in support for rational number arithmetic which have an economy of expression for literals as well as expressions with support from the language to catch errors and to convert text representations at compile-time instead of run-time.Pervert
"Most do, but some use an API which falls back to using string literals containing numeric literals which must be parsed at runtime" That's basically the same as a UI, and probably the right thing to do. Unless all of your users are going to follow you to a funky language, you'll still need to support that.Unhorse
@Unhorse Very nearly all of the programming languages I have seen or used over the past 40 years or so have emitted some amount of funk. Though, some have been decidedly worse than others...Pervert
It does not seem like this is a floating-point question. In a comment, you describe the text representation of numbers as consisting of numerals (by which I think you mean digits), a sign, a decimal/radix separator, and grouping separators. A floating-point number also has an exponent, to make the decimal/radix point float.Feingold
You ask in the question for compile-time conversion of numbers but mention in comments that numbers will also be entered by users. This means you will have to support run-time conversion, which makes it unclear why there is any necessity for compile-time conversion. Perhaps it might be more convenient to have a compiler convert and do checks, but these can also be done at run-time. The checks could also be done with various test mechanisms, so they do not need compiler support. Why is compile-time conversion such a critical need?Feingold
@EricPostpischil I did unintentionally omit the mention of an exponent. In any case, all text representations of numbers, including those with integer exponents, represent finite rational numbers. As such, they can be parsed into objects representing rational numbers, perhaps with the necessity of using arbitrary precision integers for the numerator and denominator. In any case, there are no shortage of good implementations for rational numbers of arbitrary precision arithmetic. However, I am looking for languages in which a decimal number literal is not always translated to an IEEE FP number.Pervert
I already deal with parsing numbers from user input and then handing strings or integers to constructors, methods, or functions which return a rational number or arbitrary precision number. While cumbersome in some implementations, it is not what I am trying to avoid or the point of my question. I am simply looking for languages which have good implementations for arithmetic which is not limited to fixed-bit integers or IEEE floating-point and which also support and comprehend literals for those numbers -- e.g. rational numbers and arbitrary precision decimal notation.Pervert
@NedNowotny: We understand what you say you are looking for. But I still would like to know why. Why do you specify a requirement for compile-time handling of literals when it does not appear to be necessary for your ultimate goals? It appears to be an added requirement without justification.Feingold
Except that, in this question, my goal is specifically to find candidate languages which have other properties I may want, but which specifically include numeric literals for numbers which are not simple integers and which are not to be translated into IEEE floating-point representation with the potential for a loss of precision I do not want in cases where I would want this feature. The languages I have used to date are verbose in varying degrees and often carry an unnecessary run-time overhead to produce a number value from a string literal.Pervert
let us continue this discussion in chatPervert
P
3

Haskell has Rationals backed by arbitrary precision Integers, and it has overloaded numeric literals, so that most often your literals have exactly the type you want.

Permeance answered 16/1, 2014 at 10:5 Comment(1)
Of the currently available programming languages, Haskell most directly provides what I was asking for. It is also the most widely used and written about of any of the alteratives I have investigated or had recommended -- though even Haskell's popularity is very limited when compared to the most widely used languages. In contrast to languages such as Julia, its syntax and semantics are more daunting for programmers who are not already well versed in mathematical notation and concepts. In any case, this is the kind of answer I was seeking. Thank you.Pervert
C
2

In Smalltalk, Visualworks extended the st-80 syntax in order to introduce 1.23s which is an instance of FixedPoint (not that a good name...), internally represented as the rational Fraction 123/100

The number behaves exactly like a Fraction, which can have arbitrary long numerator and denominator, and performs exact arithmetic, except that it has some specific rules for printing: it round to a fixed number of decimal after decimal fraction separator. 1.23s4 rounds to 4 decimals -> '1.2300' 1.23s rounds to provided number of fraction digits thus 2.

After Visualworks, most Smalltalk dialects added some equivalent classes and same literal syntax. In Squeak, the class is named ScaledDecimal, but only the 1.23s2 syntax has been implemented in Compiler. Pharo is going to also include 1.23s in release 3.0.

Coad answered 16/1, 2014 at 3:50 Comment(0)
B
0

In Scheme, there are two kinds of numbers, exact and inexact, a distinction which is orthogonal to numeric types (integer, rational, real, complex). Operations on inexact numbers produce inexact results, and inexact numbers are typically implemented as IEEE floats. For convenience, a numeric literal with a decimal point or exponent is assumed to be inexact, and one without is assumed to be exact, so 1 and 1/10 and 1+2i are exact, whereas 1.0 and 0.1 and 1.0+2.0i are inexact. But you can override this by preceding the literal with #e to make it exact or #i to make it inexact, so #e3.0 is the same as 3, #e0.1 is the same as 1/10, and #i1/10 is the same as 0.1.

Bullock answered 15/2, 2015 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.