
Hi. I'm working with simple functions involving rational exponents. I noticed that the (**) function seems to do okay with negative powers, but that something else is needed for rational exponents: Prelude> 2 ** (-2) 0.25 Prelude> 8 ** (1/3) 2.0 Prelude> 8 ** (2/3) 3.9999999999999996 Would there be a module meant for that sort of thing? I spent some time in Hoogle and Hackage looking around, but nothing obvious stood out. -- frigidcode.com theologia.indicium.us

On Wed, Sep 7, 2011 at 16:25, Christopher Howard < christopher.howard@frigidcode.com> wrote:
Hi. I'm working with simple functions involving rational exponents. I noticed that the (**) function seems to do okay with negative powers, but that something else is needed for rational exponents:
Nothing else is needed; you're just seeing the inevitable failure mode of floating point math (once you get into exponents that aren't integers, you can't escape it). You may want to restrict printing precision. (No, this is not a bug. No, there is no workaround that magically makes floating point behave the way new users think it should. And no, this is absolutely *not* Haskell-specific; the same kind of question constantly comes up with C, C++, Perl, Java, PHP, ....) -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On Wednesday 07 September 2011, 22:38:21, Brandon Allbery wrote:
On Wed, Sep 7, 2011 at 16:25, Christopher Howard <
christopher.howard@frigidcode.com> wrote:
Hi. I'm working with simple functions involving rational exponents. I noticed that the (**) function seems to do okay with negative powers, but
that something else is needed for rational exponents: Nothing else is needed; you're just seeing the inevitable failure mode of floating point math (once you get into exponents that aren't integers, you can't escape it).
One could have an exact (??) :: Rational -> Rational -> Maybe Rational so that (r % s) ?? (p % q) = Just (n % d) if r^p == n^q && s^p == d^q, Nothing otherwise (if r < 0, p even, q odd, then n has to be chosen negative). But when dealing with floating point numbers, you can only get the occasional correct result by accident.
You may want to restrict printing precision.
Or round to k bits. Or write a function rationalPower :: Floating a => a -> Rational -> a which calculates the power e.g. by Newton's method. That would still give incorrect results most of the time, but could produce exact results in cases where the exact result is representable and all involved numbers are such that no overflow occurs.

On 09/07/2011 12:38 PM, Brandon Allbery wrote:
On Wed, Sep 7, 2011 at 16:25, Christopher Howard
mailto:christopher.howard@frigidcode.com> wrote: Hi. I'm working with simple functions involving rational exponents. I noticed that the (**) function seems to do okay with negative powers, but that something else is needed for rational exponents:
Nothing else is needed; you're just seeing the inevitable failure mode of floating point math (once you get into exponents that aren't integers, you can't escape it). You may want to restrict printing precision.
(No, this is not a bug. No, there is no workaround that magically makes floating point behave the way new users think it should. And no, this is absolutely *not* Haskell-specific; the same kind of question constantly comes up with C, C++, Perl, Java, PHP, ....)
-- brandon s allbery allbery.b@gmail.com mailto:allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms
Are there any alternative approaches that could taken? Perhaps, some kind of Floating Ratio implementation? Prelude Data.Ratio> 8 ** (2 % 3) <interactive>:1:3: No instance for (Floating (Ratio a0)) arising from a use of `**' Possible fix: add an instance declaration for (Floating (Ratio a0)) In the expression: 8 ** (2 % 3) In an equation for `it': it = 8 ** (2 % 3) Or maybe an all-rational math? I'm mainly curious as my CASIO fx-115W calculator returns a result of exactly 4 if I input 8^(2/3), but I do not know how it arrives at the answer. -- frigidcode.com theologia.indicium.us

On Wed, Sep 7, 2011 at 17:32, Christopher Howard < christopher.howard@frigidcode.com> wrote:
Or maybe an all-rational math? I'm mainly curious as my CASIO fx-115W calculator returns a result of exactly 4 if I input 8^(2/3), but I do not know how it arrives at the answer.
Calculators often resort to built-in tables. The easiest solution is probably to round off the last 2 digits of the full precision. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On Wednesday 07 September 2011, 23:32:28, Christopher Howard wrote:
Are there any alternative approaches that could taken? Perhaps, some kind of Floating Ratio implementation?
That's not sanely possible. Floating demands pi and functions like log, exp, sin... which usually have irrational values. Since Rational contains no "closest value to the true result", a Floating instance for Rational would be very evil.
Prelude Data.Ratio> 8 ** (2 % 3)
<interactive>:1:3: No instance for (Floating (Ratio a0)) arising from a use of `**' Possible fix: add an instance declaration for (Floating (Ratio a0)) In the expression: 8 ** (2 % 3) In an equation for `it': it = 8 ** (2 % 3)
Or maybe an all-rational math?
That's possible to a certain extent, but in most cases powers with non- integer exponents will again be irrational, so those couldn't be done.
I'm mainly curious as my CASIO fx-115W calculator returns a result of exactly 4 if I input 8^(2/3), but I do not know how it arrives at the answer.
Probably it's something like Prelude> 8 ** (2/3) :: Float 4.0 With the right number of bits in the type, the errors cancel for certain calculations.
participants (3)
-
Brandon Allbery
-
Christopher Howard
-
Daniel Fischer