-
Notifications
You must be signed in to change notification settings - Fork 113
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
Wrong division result with cpp_dec_float #368
Comments
Hmmm... For some reason, I can not, at the moment reproduce this behavior. I tried with Boost 1.77 and both VC14.2 and GCC 9.3 on x86_64-linux-gnu and got Could you please provide more information on the compiler/Boost-version you are using to obtain this result? |
I'm fairly sure this is a result of the cpp_dec_float not performing any rounding (and having guard digits), but @ckormanyos will no doubt confirm shortly. |
Thanks john. That's what I thought at first, ... but...
... actually, I am having difficulty reproducing the result. I obtain So I would like to find out the compiler/Boost-version/target-system exhibiting this phenomenon. |
I'm using boost 1.73 with visual studio 16.11.2. The compilation is done in 32 bits. I've tried with more decimals (50). This time, the result is smaller than 375. #include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
using decimal = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
boost::multiprecision::et_off>;
int main (int argc, char* argv[])
{
decimal a = decimal {"69000"} / decimal {"184"};
decimal b = floor (a);
decimal c = ceil (a);
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
std::cout << "c = " << c << std::endl;
double a2 = 69000.0 / 184.0;
double b2 = floor (a2);
double c2 = ceil (a2);
std::cout << std::endl;
std::cout << "a2 = " << a2 << std::endl;
std::cout << "b2 = " << b2 << std::endl;
std::cout << "c2 = " << c2 << std::endl;
return 0;
} The above program shows:
I will try to upgrade to boost 1.77. |
Yes, please try that. If the behavior is different/correct, then i would also take the time on our side to backtrace to 1.73 and figure out what did/is going on. For me this one is, ... to be continued. But if oyu get a chance, please report your experienc with a more modern Boost. I did a big refactor of |
I'm using vcpkg as package manager. In vcpkg, boost 1.77 is not present yet. However, I confirm that I have the same issue with boost 1.76. |
I can reproduce and confirm the errant behavior as reported on 1.76. This phenomenon has been corrected in 1.77. As a next step I will figure out why. I am rather sure it is the refactor of |
This issue points out that The good news is that the long-term plan is to correct all these. The bad news is that some calculations of the genre reported above still fail with 1.77. I wrote the program below to scan thousands of test cases and found several distinct failure modes on the
I'll correct these in the long term on |
Summary:
Keep this issue open. |
Thanks for the update. It doesn't seem like an easy problem to solve. Take all the time necessary for the most appropriate approach. I'm afraid I can't help on how to fix it... |
Indeed. Thanks for the clear report. The phenomenon you found is a bug and we have classified this as a bug. I will try to fix this for 1.78. Probably the first fix will involve rounding and slight refinements to |
I noticed a very similar problem, asked in StackOverflow, a comment pointed me here. My test case is super simple, I'm dividing Full repro and output below:
This produces
This is on MacOSX,with This behavior effectively prohibits using boost::multiprecision for some applications. EDIT: just in case also tested on Linux, with |
Hi @MarcinZukowski thank you for pointing this out. Your observations are correct. Unfortunately, I have not yet found time to correct this issue, which is, in fact, marked as a bug.
Thanks for your query and clear statement, as this adds motivation for us to fix this. |
Hi, I found a similar issue: https://wandbox.org/permlink/Ly2kN6A7Fza0Jo26
Produces:
|
Thanks for the report @jeteve. This issue remains open and marked as a bug. I do not yet have the proper codes for a fix, but the issue has not been forgotten. Kind regards, Chris |
Hi Kevin (@kevin-1016) thank you for looking into this. As far as i can tell, you have found the rounding problem. This is the same problem in this thread: The Unfortunately, however, I think the the lines of code you mention are not the root cause of this problem. The comment Handle a potential carry in this particular case might be in the wrong place, or the comment is not adequately informative. In that part of the code, there might be a carry resulting from multiplication and the entire internal storage array needs to be shifted one element down in order to make room for the carry result. I could do a bit better with the clarity of the comment, but basically we have a case where all those trailing nines should have resulted in internal rounding. But there is no rounding. So the result stays very near to, but not exaclty
|
But I got the correct result after result.cbegin()+1
|
I mean, although cpp_dec_float is not exact, it takes six decimal places for boost172, but only five decimal places for boost182, which causes this problem. As long as I change the decimal length to 6, it's fine. |
Hi @kevin-1016 in the code you posted just above, the copy operation could extend beyond the range of You see in the proposed change,
you could end up copying to the end-range of
and that can't be quite right. I will investigate further. But I fear, |
Ah. Yes, @kevin-1016, I am finally comprehending your point. Sorry it took a few iterations for me to grasp your point.
This statement from myself might be incorrect since the buffer of the multiplication result is wider than the destination range.
I will run more local tests and CI. I'm not sure if this is complete rounding, but it might improve |
See also #585 resulting in reduction of truncation in Cc: @kevin-1016 (with many thanks) |
I have switched the labels on this issue to enhancement and low priority. The next step to undertake would be trivial rounding on |
See also #604 |
I'm using cpp_dec_float to don't deal on rounding issues when mathematic operations give some results with an exact base-10 representation. The result of 69000 / 184 = 375. With cpp_dec_float, it is a bit more.
The above program shows:
The text was updated successfully, but these errors were encountered: