-
Notifications
You must be signed in to change notification settings - Fork 183
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
Decimal precision mismatches against Python Decimal #471
Comments
Great write up, thank you. I'll need to look into this more, however from first glance it is triggered by how Rust Decimal currently handles underflow. I suspect Python doesn't round and possibly has an extra bit or two of precision, whereby Rust Decimal currently does (i.e. the same as .NET). Calculating by hand:
For Rust Decimal it's that hanging 29th significant figure which it can sometimes represent, and sometimes not (See here for a good explanation). It can guarantee 28 with its current layout so that's why it rounds in this case. I'll look into it some more to see how possible it is though. I think it's a reasonable request and something I'd love to see how we could modify to cater for this behavior. |
I've done a little investigating into this. For the fourth example the Rust library rounds to fix everything into a 96 bit mantissa. For this, it rounds up from the 5 hence why we see the value The decimal behind the scenes uses the following:
Now, if we look at what the python mantissa is we can see that it is likely storing the following:
More interesting is taking a look at the binary representation: Unfortunately, as the library currently stands, this is not possible in Rust Decimal since we cap the mantissa to the 96 bit boundary. This allowed us to make various assumptions in regards to operations allowing us to squeeze out extra speed optimizations. That being said, as part of v2 I think it'd be useful for two modifications:
I'm currently experimenting with this however unfortunately it's not a quick fix so doesn't have a known timeline. Allowing flag overflow is a good first step however does require a fair bit of change to support. I'll keep this example in mind as I investigate solutions, though I will say that the best way to guarantee equality is to use the same library on both sides. e.g. use |
Since you mentioned pyo3, I'm trying to get support for rust_decimal in via PyO3/pyo3#3016 |
Hey all,
I know there have been some conversations around precision (re: #414 ), but wanted to post a different question on the topic for guidance/support:
CONTEXT:
We have a Rust codebase that performs computations (using this
rust-decimal
module) and outputs a record of the inputs to these computations. We have a Python sister codebase that receives this log and attempts to perform the exact same computations (using the Decimal module) to arrive at the same results.We noticed that on occasion, there are ever so slight discrepancies.
REPRO:
FYI: For Python, we set the
Decimal
module's context to be the following:We chose these values after studying the
Decimal
module and attempting to match howrust-decimal
handles arithmetic. In particular, we believe theseEmin
andEmax
values give us ane
in the range of [-28, 0], and theprec
setting of 29 (as opposed to the default value of 28) would allow us to represent 29 digits sincerust-decimal
can support numbers as large as 2 ** 96 - 1 (which has 29 digits).Case 1 (Matches) ==> 5631989.747461568422879160 + 12354.867325583148587639999525:
Case 2 (Matches) ==> 6631989.747461568422879160 + 12354.867325583148587639999525:
Case 3 (Matches) ==> 7631989.747461568422879160 + 12354.867325583148587639999525:
Case 4 (Does not match) ==> 8631989.747461568422879160 + 12354.867325583148587639999525:
DISCUSSION:
Given how widespread the usage of
rust-decimal
and Python'sDecimal
modules are (appears to be the dominant decimal packages in both languages), it seems there should be a way to synchronize both implementations. Is there a way to haverust-decimal
's output match that of Python's, or set up the PythonDecimal
module's context using theprec
,Emax
,Emin
fields, etc. (or transform the output) to identically mimic the behavior of this module?The text was updated successfully, but these errors were encountered: