> 1.1 + 2.2
3.3
> 1.1 + 2.2 == 3.3
True
EDIT: to be clear: this is not because Raku is magic, it's because Raku defaults to a rational number type for decimal literals, which is arguably a much better choice for a language like Raku. > 1.1 + 2.2
3.3
> 1.1 + 2.2 == 3.3
True
EDIT: to be clear: this is not because Raku is magic, it's because Raku defaults to a rational number type for decimal literals, which is arguably a much better choice for a language like Raku. * (= (+ 0.1 0.2) 0.3)
T
In Common Lisp, there is a small epsilon used in floating-point equality: single-float-epsilon. When two numbers are within that delta, they are considered equal.Meanwhile, in Rakudo, 0.1 is a Rat: a rational number where the numerator and denominator are computed.
You can actually get the same underlying behavior in Common Lisp:
(= (+ 1/10 2/10) 3/10)
Sadly, not many recent languages have defaults as nice as those. Another example is Julia: julia> 1//10 + 2//10 == 3//10
true
IMO, numerical computations should be correct by default, and fast in opt-in.Edit: it seems that Raku uses rationals as a default [1], so it doesn't suffer from the same problem by default.
Yeah, exactly, Raku defaults to a rational number type for these kinds of numbers. I honestly think that is a perfectly fine way to do it, you're not using Raku for high performance stuff anyway. It's not so different from how Python will start to use arbitrarily sized integers if it feels it needs to.
Raku by default will convert it to a float if the denominator gets larger than a 64-bit int, but there's actually a current pull request active that lets you customize that behavior to always keep it as a Rat.
Really interesting language, Raku!
0.1e0 + 0.2e0
yields 0.30000000000000004. Your example also fails 1.1e0 + 2.2e0 == 3.3e0
returns false.Having developed a significant amount of perfect precision math libs over the years, rationals do explode for lots of common computations. That is the main reason they are not standard in all computing. They also cannot represent a lot of desired results.
The problem is rational number performance slows exponentially (or uses large amounts of RAM) for many common uses, which will kill scripts, unless they suddenly fix precision (i.e., no longer exact) or change to float (also a surprise for people).
Setting them as floats has the odd numerical issue, which is not that bad, but doesn't require a host of other mitigations to prevent other bad surprises.
For example, summing 1/n^2 for n=1 to 100000 as floats runs quickly and is very close to the exact answer. As rationals the numerator and denominator require working with 86000 digit numbers.
Also, does raku still do this?
say (1/6+1/6).raku #<1/3>
say (1/10+1/10).raku #0.2
That seems surprising, does it not?
both are Rats, they just get stringified differently