This example also reminds me of why golang won’t soon become my favorite language. It’s just not expressive enough for this kind of stuff. If you’re using rationals, you really want to be able to write
Maybe, but they’re giving up at least one bit by making both numerator and denominator signed.
Thinking more about this, I think most implementations of rational use some bigint type for both numerator and denominator, completely solving that issue.
That isn’t performant, but I can’t think of code that needs rationals that doesn’t need exactness, and if you don’t need exactness, floating point will do fine.
I would say you "need" rationals, when there is no reason to give an incorrect or imprecise result and performance is not that important or input size is not too big.
When you need that kind of precision for irrational numbers, you can opt for symbolic calculation, where important irrational numbers are simply symbols or terms and you can transform them at the end of the calculation into a number of as much precision, as you need. Of course there are always edge cases, where finding a good solution is difficult. For example, what if you need performance and as much precision as possible? Cannot use floating point numbers, cannot use rationals with same performance as floating point numbers (I think), cannot use symbolic calculation, also because of performance ... Not sure what to do then, but I have not hit such a case ever. I imagine, that perhaps space operations need that kind of precision. Perhaps they simply have clusters run for a few days or so, to get to that precision.
Any iterative algorithm could compound its own rounding errors until the final result is nonsense. This created the need for a theory of https://en.wikipedia.org/wiki/Numerical_stability and tweaking algorithms to do the same things in a different order that happens to blow up less often. In some ways fixed point would be safer or at least more predictable.
In some ways fixed point would be safer or at least more predictable.
Outside a laboratory setting, there are very few real world problems that can't be adequately addressed with scaled integers (fixed point math).
Most things have practical limits imposed on accuracy. Most monetary transactions are legally required to be settled in pennies (at least in the US). Most time periods are recorded in minutes or seconds. Most thermometers are only accurate to 1/10 of a degree. Attempting to exceed these practical, real world limits is really just "false accuracy" that causes more problems than it solves.
Equating these two is just an approximation ... and based on the example, one that was carried out without any obvious accuracy requirement.
So why not 1 65/97 which is more accurate or 1 67/100 which is perfectly accurate?
Messing around with fractions is still only an approximation at best so it's hard to see how this really buys you much of anything except lost efficiency. Why not just use floats and format as a fraction for display/output if this is what "floats" your boat?
The heading is misleading I think. Fractions have been in other programming languages for decades. There is nothing new about fractions. It is a basic feature of number systems in programming languages. It often helps with being precise in calculations. I've been using them for a long time in Scheme dialects.
The heading should be: "Finally a Golang library that retrofits Golang with a fractions datatype." -- relating only to Golang, instead of creating the wrong impression, that this is anything new in programming.
12 comments
[ 4.2 ms ] story [ 31.8 ms ] threadAlso, for FloatToFrac, you may want to look into continued fractions. They make it extremely easy to find better and better rational approximations to any number (https://en.wikipedia.org/wiki/Continued_fraction#Best_ration...)
This example also reminds me of why golang won’t soon become my favorite language. It’s just not expressive enough for this kind of stuff. If you’re using rationals, you really want to be able to write
and get 149/208 as output.I'm guessing accuracy. This way, the numerator and denominator have more range to represent just the fractional part.
Thinking more about this, I think most implementations of rational use some bigint type for both numerator and denominator, completely solving that issue.
That isn’t performant, but I can’t think of code that needs rationals that doesn’t need exactness, and if you don’t need exactness, floating point will do fine.
I can't think of code that really needs rationals.
Irrational numbers are proof that numeric "exactness" is relative.
When you need that kind of precision for irrational numbers, you can opt for symbolic calculation, where important irrational numbers are simply symbols or terms and you can transform them at the end of the calculation into a number of as much precision, as you need. Of course there are always edge cases, where finding a good solution is difficult. For example, what if you need performance and as much precision as possible? Cannot use floating point numbers, cannot use rationals with same performance as floating point numbers (I think), cannot use symbolic calculation, also because of performance ... Not sure what to do then, but I have not hit such a case ever. I imagine, that perhaps space operations need that kind of precision. Perhaps they simply have clusters run for a few days or so, to get to that precision.
Most things in the real world simply can't be measured to a level of accuracy beyond 4 decimals.
They also can come in handy in various puzzle problems.
Outside a laboratory setting, there are very few real world problems that can't be adequately addressed with scaled integers (fixed point math).
Most things have practical limits imposed on accuracy. Most monetary transactions are legally required to be settled in pennies (at least in the US). Most time periods are recorded in minutes or seconds. Most thermometers are only accurate to 1/10 of a degree. Attempting to exceed these practical, real world limits is really just "false accuracy" that causes more problems than it solves.
Equating these two is just an approximation ... and based on the example, one that was carried out without any obvious accuracy requirement.
So why not 1 65/97 which is more accurate or 1 67/100 which is perfectly accurate?
Messing around with fractions is still only an approximation at best so it's hard to see how this really buys you much of anything except lost efficiency. Why not just use floats and format as a fraction for display/output if this is what "floats" your boat?
The heading should be: "Finally a Golang library that retrofits Golang with a fractions datatype." -- relating only to Golang, instead of creating the wrong impression, that this is anything new in programming.
> Go provides rational numbers in the standard library, in the math/big package (https://pkg.go.dev/math/big#Rat)