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
struct.pack of floats in non-native endian order #38176
Comments
Python version 2.1 (2.2.1 behaves the same). This was run on an Intel platform. >>> v = 7.0 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1
+ .1
>>> v
7.9999999999999964
>>> struct.pack( "f", v )
'\x00\x00\x00A'
>>> struct.pack( ">f", v )
'@\x80\x00\x00' These two should be the same byte pattern (only >>> struct.unpack( ">f", '@\x80\x00\x00' )
(4.0,) !!!!! |
Logged In: YES Yuck. It's a bug in not accounting for that rounding can Note: while "<f"'s result should be the byte-reversal |
Logged In: YES Boosted priority because this is an especially bad kind of For 2.2 I expect to check in a quick hack. In 2.3 this code |
Logged In: YES Thanks for getting back to me. Your comment regarding IEEE formats is very interesting, I |
Logged In: YES Fixed. In the 2.2 branch: Lib/test/test_struct.py; new revision: 1.14.12.1 For 2.3: Lib/test/test_struct.py; new revision: 1.17 |
Reopening. The test case committed in r31892 is broken, specifically the part that checks for an OverflowError towards the end: the TestFailed exception is only instanced, never raised. Actually raising the TestFailed instance causes the test to fail. |
A lot of water passed around this bridge, but I don't know if this is fixed: In the trunk right, now: >>> v = 7.0 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1
>>> v
7.9999999999999964
>>> p = struct.pack( ">f", v )
>>> p
'A\x00\x00\x00'
>>> struct.unpack(">f", p)
(8.0,) |
It's a little odd: the relevant code is in floatobject.c, in _PyFloat_Pack4. The
I think the behaviour should be consistent: either always raise OverflowError or One the OverflowError/infinity decision is made, this is a relatively easy fix, Christian, do you have any thoughts on this issue? |
Aha: the �C99 standard, section 6.3.1.5, says: When a double is demoted to float, a long double is demoted to double or So the current code likely has different behaviours even on different IEEE-754 platforms. |
Here's a patch that fixes the test that Collin mentioned to reflect what's actually been When packing a float that's too large for the destination format (e.g. pack(">f", 1e39)):
This patch doesn't fix the problem that the cast from double to float on IEEE machines |
Sounds like a good idea to me. Although all major platforms support IEEE The lines should be a safe replacement of the downcast:
double fromd;
float tof;
tof = abs(fromd) >= FLT_MAX ? FLT_MAX : fromd;
tof = (float)copysign((double)tof, fromd); By the way the release notes of Python should mention the our work on |
I'm stealing this issue from Tim, and downgrading the priority to normal |
Coming back to this, I think that it actually *is* clear what The attached patch (705836_v2.patch) fixes this. All tests pass with I'll leave this around for a few days in case anyone wants to comment on |
Fixed in r61383. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: