-
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
Optimize BigInteger.ToString
for large decimal string
#112178
base: main
Are you sure you want to change the base?
Conversation
Tagging subscribers to this area: @dotnet/area-system-numerics |
|
||
int cuDst = 0; | ||
// The Ratio is calculated as: log_{10^9}(2^32) | ||
const double digitRatio = 1.0703288734719332; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it worth to do a FP calculation, instead of conservatively allocate for upper limit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's not much difference, but the required storage size will be smaller. For example, when the bit length is 58 or 59, stackalloc is used.
_bit.Length | old | new |
---|---|---|
57 | 64 | 62 |
58 | 65 | 63 |
59 | 66 | 64 |
This change also aims to achieve mathematical correctness in the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either stack allocation or array poll will round the requested size up to whole number. Such difference should be really negligible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When coming with FP arithmetic, it's also important to make sure rounding doesn't give you smaller integer result for corner cases. That's why I'm suggesting against FP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rounded up the value of digitRatio
from Math.Log(1L<<32, 1e9)
, to double
has higher precision than int
, unintended rounding down has become theoretically impossible.
src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs
Outdated
Show resolved
Hide resolved
efcf4e1
to
bf75784
Compare
bf75784
to
86f4a53
Compare
2abfe84
to
f825641
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
Comments suppressed due to low confidence (3)
src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs:797
- [nitpick] The variable name 'digitRatio' is ambiguous. It should be renamed to something more descriptive like 'logBase2ToBase1E9Ratio'.
const double digitRatio = 1.070328873472;
src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs:933
- [nitpick] The method name 'BigIntegerToBase1E9' could be more descriptive. Consider renaming it to 'ConvertBigIntegerToBase1E9'.
private static void BigIntegerToBase1E9(ReadOnlySpan<uint> bits, Span<uint> base1E9Buffer, out int leadingWritten)
src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntegerToStringTests.cs:13
- The variable 'result' is initialized to 'null' but is not explicitly set in the 'catch' block, which could lead to a 'NullReferenceException'. Ensure 'result' is properly handled in the 'catch' block.
string result = null;
This PR is a counterpart to #55121. divide-and-conquer algorithm
Number.FormatBigInteger()
can run inThe computational complexity of division have been improved by #96895.
Benchmark
Code