New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
trying to add round for c #1193
base: devel
Are you sure you want to change the base?
Conversation
See PR #996 We have not found a way to fix this other than by using the same technique that python uses internally (convert to str then back to int) |
Should I keep working on this or just stop, since someone is already, working on it(I just saw that it was getting fixed on the 996) |
As you prefer @nandiniraja348 doesn't seem to be working on this anymore. I have occasionally been working on it when I have time but I don't have much time at the moment. Another option would be for you to pick up @nandiniraja348 's fork and complete it. I think I prefer the version in that PR as:
All that is missing there is the C function |
Okay, I'll try to do that |
I changed the way the round function worked to approximately the same as #983. I added tests to check for all the results, but still had issues with this case: def testNdigitsEdgeCases():
f = epyccel(roundNdigits, language='c')
x = 2.675
n = 2
print("testNdigitsEdgeCases 2")
print(x, n)
f_output = f(x, n)
python_output = roundNdigits(x, n)
print(f_output, python_output)
assert isclose(f_output, python_output, rtol=RTOL, atol=ATOL)
assert isinstance(f_output ,type(python_output)) where the number is unexpected in the python version(I get 2.68 which makes sense, but we get 2.67 from python), also I wanted to make the conversion internally to get it close to the python result but found out that there are way too many edge cases for that and the implementation is going to be hard, so I wanted to ask if there are any better solutions for this. |
This is very strange behaviour. It is not a normal round or a banker's round :| Python's implementation of round can be found here: It converts the float to a string then back to a truncated float. This seems to be necessary for integers at least (see failing test on #996 ) to avoid floating point imprecision leading to the wrong value. But I don't see why it ought to be necessary for floats and I imagine it will be significantly more costly than what is implemented currently. @yguclu what do you think? |
I ran the failing test on #996 on a Ubuntu image and it didn't fail, is it a problem only with windows ? |
I don't think so. It's a floating point problem. If the closest floating point number to 230 that can be stored in the computer's memory is 229.999999999999 and you convert to an int you will get 229 instead of 230.
The implementation I linked to is for floats, here's the integer version Given that the round function is in the c side of the python code, one would hope that the guys at python have already spent some time getting something reasonably optimised. |
That makes sense, I'll look more into this tomorrow
I don't think there are any other simpler methods and we probably have to follow their steps because trying to get a solution around this is probably unachievable. |
what if we make a special function for the integers like 230, for example, if we get round(230, -1) we check if the first argument type is an integer and we call a function that takes |
That is possible. But I'm not sure this is restricted to ints. For example |
I think that's what happens in the failing case we have |
This is why this issue's been sitting around for so long ^^'. I think it is quite complicated so I don't think it's worth looking for shortcuts. I think we should just implement what python does |
yeah, I don't think we can quite find a way around this, I'll try to understand the CPython solution for this and see if I can do the same on our end. |
Hey, I have this problem where sometimes python gives a surprising behavior as described in the documentation -> "https://docs.python.org/3/library/functions.html#round" I was wondering if there is a way to go around this issue. Thanks in advance.