Mathematica. But it's not particularely fast.
> Unless you're using numbers that scale from very small to very large, like 3d games or scientific calculations, you don't actually want to use floating point.
Unfortunately, we can sometimes only use floats in 3D graphics and floats aren't even good for semi-large to large 3D scenes. Unity is a particular bad offender. It's not even necessary for meshes but having double precision transformation matrices would make life so much easier. Could simply use double precision world and view matrices, then multiply them together and the large terms would cancel out in the resulting worldView matrix, which can then by cast back to single precision floats.
I'm not aware of any language (other than Wolfram) that defaults to storing something like 0.1 as 1/10 - i.e. uses the decimal constant notation for rationals, rather than having some secondary syntax or library.
In[1]:= Precision[0.1]
Out[1]= MachinePrecision
In[2]:= Precision[1/10]
Out[2]= \[Infinity]I don't currently have a license, so out of curiosity is 0.3 == 3/10 in wolfram?
According to the documentation of Equal†,
> Approximate numbers with machine precision or higher are considered equal if they differ in at most their last seven binary digits (roughly their last two decimal digits).
Which is why in Mathematica, 0.1+0.2==0.3 is also True.
If you need a kind of equality comparison that returns False for 0.3 and 3/10, use SameQ. Funnily, SameQ[0.1+0.2,0.3] is also True, because SameQ allows two machine precision numbers to differ in their last binary digit.
Casting to bigint doesn't work because the problem occurs when converting the decimal constant in the source to floating point. You would have to convince the parser to parse the constant as something besides a float.