0

I have an issue on where my double value lose precision when copied. Here is two stucts and a std::map where the value are stored:

struct orderlist{
    double price = 0;
    double quantity = 0;
    double id = 0;
    int pairID = 0;
    int order_type;
};

struct bookOrder{
    double price = 0;
    double quantity = 0;
};

std::map<double, bookOrder>* put_orders;
std::map<double, bookOrder>* ask_orders;

Then here is the code to extract the best prices :


double orderbook::getLowestAsk(){
    bookOrder ord;
    std::lock_guard lock(m_mutex);

    ord = ask_orders->rbegin()->second;
    return ord.price;
}

double orderbook::getHighestBid(){
    bookOrder ord;
    std::lock_guard lock(m_mutex);

    ord = put_orders->begin()->second; // put_orders first entry struct contain price of 54.87
    return ord.price; // ord.price is 54.869999999999997
}

For example, if the price stored into a stuct in the map is 54.87 (I clearly see that proper number in the debugger) then on the "ord = put_orders->begin()->second;", it assign the value 54.869999999999997 to price. I did not do any conversion, it's double everywhere.

scohe001
  • 15,110
  • 2
  • 31
  • 51
  • 1
    Floating point numbers are an *approximation*. Copying a double to a double will *not* change the binary value of your double. You *might* see a different *representation* in a "printf()", or in the debugger: [c++ precision issue in storing floating point numbers](https://stackoverflow.com/questions/22163559/c-precision-issue-in-storing-floating-point-numbers) – paulsm4 Oct 22 '20 at 20:44
  • @paulsm4 That's about losing precision when assigning from a literal, not assigning from one variable to another. – Barmar Oct 22 '20 at 20:45
  • 3
    `54.87` can't be represented exactly in floating point. The debugger is probably just not showing you all the digits. – Barmar Oct 22 '20 at 20:46
  • https://stackoverflow.com/questions/27149894/does-any-floating-point-intensive-code-produce-bit-exact-results-in-any-x86-base <- maybe you are running into some of the madness around 64/80 bits –  Oct 22 '20 at 20:47
  • Required reading: [Is floating point math broken?](https://stackoverflow.com/q/588004) – 001 Oct 22 '20 at 20:48
  • 1
    Side note: Pointers to library containers is unusual. You almost never want to dynamically allocate one with `new` and the rest of the time you're typically using references. – user4581301 Oct 22 '20 at 20:50
  • @Barmar So I have to round it to 8 digits when I actually use the number as a solution as I understand there is no simple fix to get the same number out as the one I put in and I don't need more precision than 8 digits. I take a look, thanks. – DestroyFX Oct 22 '20 at 20:58
  • 3
    A good rule: don't use floating point for money. – Barmar Oct 22 '20 at 20:59
  • @Barmar , I'm dealing with crypto "money". Some other trading pair have a price that look like.. example for ADABTC, 0.00000863 – DestroyFX Oct 22 '20 at 21:03
  • Quoting Uncle Bob: "you can go to jail for using floating points for money". In case of money It is best to use big integer type to count number of cents or fraction of cents. – Marek R Oct 22 '20 at 21:23
  • Fixed it this way : api_parameters = api_parameters + "\"price\": "+ boost::lexical_cast(data->parameter0); parameter0 is the price in double variable – DestroyFX Oct 22 '20 at 22:13
  • @DestroyFX store a scaled integer instead, similar to banking systems store an integer representing the number of cents. For example a unit of 0.0000000001, then 86300 means 0.00000863. – phuclv Oct 22 '20 at 23:51

0 Answers0