-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
BigInteger unsigned right shift operation is poorly designed and exposes implementation details #91169
Comments
Tagging subscribers to this area: @dotnet/area-system-numerics Issue DetailsDescriptionI found a problem with the BigInteger unsigned right shift operation ( BigInteger represents an infinite-precision signed binary integer in two's complement form, but it does not have a predefined bit length. Therefore, it should not be treated as a fixed-length integer and subjected to unsigned right shift with some arbitrary or randomly chosen bit length. Unsigned right shift can be seen as performing a signed right shift ( We observe that the larger N is, the more bits are preserved, so for BigInteger, the limiting case is that all bits are preserved, which means that the natural definition of unsigned right shift in infinite precision is the same as signed right shift, because the masking operation does not change any bits. (Although BigInteger has a GetBitLength() value, using it (or its variant) as the fixed length for unsigned right shift is also not very natural.) Reproduction Steps. Expected behaviorThe BigInteger unsigned right shift operation should behave exactly the same as the signed right shift operation, regardless of the internal representation of the BigInteger. Actual behaviorThe BigInteger unsigned right shift operation is based on the internal representation of the BigInteger, and produces unexpected results when the BigInteger is negative. Regression?No response Known WorkaroundsNo response ConfigurationNo response Other informationNo response
|
This is functionally "by design". There were two options possible, one of which always treated the bit sequence as the shortest possible two's complement representation and thus Computer math is not the same as real math, it never has been and is instead a rough approximation. There are many concepts that break down in practice and which require special consideration or handling. One could also, for example, argue that It's a bit too late to change this behavior at this point and if you want the other behavior then I'd suggest you workaround it by taking the absolute value and then shifting instead. |
Description
I found a problem with the BigInteger unsigned right shift operation (
>>>
) when the BigInteger is negative.BigInteger represents an infinite-precision signed binary integer in two's complement form, but it does not have a predefined bit length. Therefore, it should not be treated as a fixed-length integer and subjected to unsigned right shift with some arbitrary or randomly chosen bit length.
Unsigned right shift can be seen as performing a signed right shift (
>>
) after masking the bits with ((1 << N) - 1). The current implementation incorrectly uses the total number of bits in the minimum number of UInt32 units needed to store the BigInteger as the fixed length N, which is inappropriate because it is unnatural and exposes implementation details. (Note that we may consider upgrading BigInteger to use UInt64 units instead.)We observe that the larger N is, the more bits are preserved, so for BigInteger, the limiting case is that all bits are preserved, which means that the natural definition of unsigned right shift in infinite precision is the same as signed right shift, because the masking operation does not change any bits. (Although BigInteger has a GetBitLength() value, using it (or its variant) as the fixed length for unsigned right shift is also not very natural.)
Reproduction Steps
.
Expected behavior
The BigInteger unsigned right shift operation should behave exactly the same as the signed right shift operation, regardless of the internal representation of the BigInteger.
Actual behavior
The BigInteger unsigned right shift operation is based on the internal representation of the BigInteger, and produces unexpected results when the BigInteger is negative.
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response
The text was updated successfully, but these errors were encountered: