Jump to content

Haskell Rounding Error using Float

Ryujin2003

Hi everyone.

 

So I'm working on some homework, and need some assistance. I have a float, say 4.3. I'm trying to separate the integer from the remainder, so it'll be output as (4, 0.3). My issue is Haskell seems to suck with floating point numbers in the rounding error department....

 

Here is my code:

 

splitFloat :: Float -> (Integer, Float)
splitFloat num
    | num >=0 = (w,r)
    where
      w = (floor num)
      r = (num-fromInteger(w))

 

My issue is at r, when I perform the math, I get 0.29999999999998.... Which isn't the answer I'm trying to get. I have done the math in eMacs using the Haskell terminal, and even manually typing 4.3 - 4.0 gives me 0.29999....

 

Round only works on Integers, so my remainder is rounded to 0. I cannot seem to find anything that fixes this. I never had this much trouble in C++ or Java. I'm not looking for specific code since this is my homework assignment after all. But some insight into what mechanics inside Haskell would permit this to work without a rounding error.

Edited by Ryujin2003
fixed code format
Link to comment
Share on other sites

Link to post
Share on other sites

8 minutes ago, Ryujin2003 said:

Hi everyone.

 

So I'm working on some homework, and need some assistance. I have a float, say 4.3. I'm trying to separate the integer from the remainder, so it'll be output as (4, 0.3). My issue is Haskell seems to suck with floating point numbers in the rounding error department....

 

Here is my code:

 

splitFloat :: Float -> (Integer, Float)
splitFloat num
    | num >=0 = (w,r)
    where
      w = (floor num)
      r = (num-fromInteger(w))

 

My issue is at r, when I perform the math, I get 0.29999999999998.... Which isn't the answer I'm trying to get. I have done the math in eMacs using the Haskell terminal, and even manually typing 4.3 - 4.0 gives me 0.29999....

 

Round only works on Integers, so my remainder is rounded to 0. I cannot seem to find anything that fixes this. I never had this much trouble in C++ or Java. I'm not looking for specific code since this is my homework assignment after all. But some insight into what mechanics inside Haskell would permit this to work without a rounding error.

Try using code formatting next time, helps the readability.
	Yeah.

Also, aren't there native libraries for rounding in haskell?

Want to know which mobo to get?

Spoiler

Choose whatever you need. Any more, you're wasting your money. Any less, and you don't get the features you need.

 

Only you know what you need to do with your computer, so nobody's really qualified to answer this question except for you.

 

chEcK iNsidE sPoilEr fOr a tREat!

Link to comment
Share on other sites

Link to post
Share on other sites

rounding errors are inherently computer problems - it's even it's own thing in computing science http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf

 

every language deals with float types and rounding in their own unique way

 

---

 

from what I found, people recommend using Ratio type when deaing with fractional numbers https://www.haskell.org/onlinereport/ratio.html

Edited by zMeul
Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, bob51zhang said:

Try using code formatting next time, helps the readability.
	Yeah.

Also, aren't there native libraries for rounding in haskell?

Fixed, thanks.

I looked, and there don't seem to be anything too specific. I can postfix, that that isn't going to auto-round. Most of the other rounding features appear to result in Float -> Integer, not Float -> Float.

2 minutes ago, zMeul said:

rounding errors are inherently computer problems - it's even it's own thing in computing science

 

every language deals with float types and rounding in their own unique way

So, this might be something I'll have to live with until I've got more than 2 weeks experience in Haskell? I don't really like leaving it ugly, but I can't really find anything that works. I've spent about 3 hours trying to make it pretty, and haven't figured it out yet.

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, Ryujin2003 said:

So, this might be something I'll have to live with until I've got more than 2 weeks experience in Haskell? I don't really like leaving it ugly, but I can't really find anything that works. I've spent about 3 hours trying to make it pretty, and haven't figured it out yet.

read my updated post above

I found something that might help or might send you deeper in the rabbit hole

Link to comment
Share on other sites

Link to post
Share on other sites

17 minutes ago, zMeul said:

read my updated post above

I found something that might help or might send you deeper in the rabbit hole

Thank you, I'll definitely save that for later. The professor wants us to stick to what the book has covered so far (only 2 weeks in, so she wants us to keep it simple and Float). So according to the guidelines, I'm limited to the functions within the scope of Float.

Link to comment
Share on other sites

Link to post
Share on other sites

I just tried a modulo with 1 in ruby to see the result:

Quote

irb(main):004:0> number=4.03

=> 4.03

irb(main):005:0> remainder=number%1

=> 0.03000000000000025

is the number originating from a string? because if it is that should be easy to split at the "." symbol

 

All the information is inside the floating point number and it should be possible to get that extra information without being subjected to floating point errors. if you take the bits representing the significand (403), perform some bitwise operations based on the value of the exponent (-2) you will get the value after the decimal point. Im not familiar with haskell and if this is even possible in that language. This can be done in C but haskell might be too high of a language.

 

Just email your teacher and ask if your answer is ok.

             ☼

ψ ︿_____︿_ψ_   

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, SCHISCHKA said:

I just tried a modulo with 1 in ruby to see the result:

is the number originating from a string? because if it is that should be easy to split at the "." symbol

 

All the information is inside the floating point number and it should be possible to get that extra information without being subjected to floating point errors. if you take the bits representing the significand (403), perform some bitwise operations based on the value of the exponent (-2) you will get the value after the decimal point. Im not familiar with haskell and if this is even possible in that language. This can be done in C but haskell might be too high of a language.

 

Just email your teacher and ask if your answer is ok.

These are manually input floats. Not from string or any thing going else. The only conversion is the floor makes an Integer, which is then converted back to float, so essentially a long to float. Haskell doesn't seem to have the functionality C++ did. It's ok, but I do feel a bit limited as far as functionality.

 

I'll play around with exponents, but I have to take the input and store it as a float, so I cannot count chars. I haven't do understand a way to count the decimal places that would allow me to place a proper exponent, but i'll keep looking. That looks like the better easy when I have to keep the numbers in float. Damned math.

Link to comment
Share on other sites

Link to post
Share on other sites

Try to round the number to a certain number of decimals.

You could store the exponent and mantissa seperately as integers and print those.

 

Alternatively, use fixed point math. But I think that is more of an advanced topic.

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mathijs727 said:

Try to round the number to a certain number of decimals.

You could store the exponent and mantissa seperately as integers and print those.

 

Alternatively, use fixed point math. But I think that is more of an advanced topic.

If I were to round the decimal using postfix or another mean it would still have to be rounded perfectly per user input. I would be able to force round to the 5th decimal place if someone were to put in more. Then the number given back wouldn't be the original fractional, and would then be wrong.

 

Is there a way to pull the number of decimals without taking I out as String then counting Chars? I cannot seem to find a way using Float functions.

 

And yes, I think fixed point would be a bit advanced for my needs at this point.

Link to comment
Share on other sites

Link to post
Share on other sites

try tell this. sort integer to decimal. sort command seperate integer wholenumbers. decimal for lol decimals.  result in this. 4.0 , 0.3

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×