[c++][decimal] boost.multiprecision не работает
От: anatoly1  
Дата: 19.10.15 04:53
Оценка:
Есть код, по которому можно сделать вывод, что boost_decimal не работает, как надо:
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <decimal/decimal>

using namespace std;
using decimal32 = decimal::decimal32;
using boost_decimal = boost::multiprecision::cpp_dec_float_50;

std::ostream& operator<<(std::ostream& out, const decimal32& d)
{
    out << decimal::decimal32_to_double(d);
    return out;
}

int main()
{
    decimal32 a(0.1);

    auto a2 = a+a+a+a+a+a+a+a+a+a;

    cout << a2 << "\n";

    cout << (a2==1) << "\n";

    boost_decimal b(0.1);

    auto b2 = b+b+b+b+b+b+b+b+b+b;

    cout << b2 << "\n";

    cout << (b2==1) << "\n";

    return 0;
}

Результат:
1
1
1
0

Это баг или фича?
Re: [c++][decimal] boost.multiprecision не работает
От: VTT http://vtt.to
Дата: 19.10.15 08:28
Оценка: +1
Здравствуйте, anatoly1, Вы писали:

A>Это баг или фича?


Это норма.
0.1 в double на самом деле представлено как 0.10000000000000001.
Переменная b при инициализации получает значение 0.1000000000000000055511151231257827021181583404541015625
А сумма b2 1.000000000000000055511151231257827021181583404541015625
При сравнении (b2==1) b2 не приводится к int, а наоборот.
Если написать (static_cast<int>(b2) == 1), то результат будет true.

Ну или можно сделать так:
  boost_decimal b2(1);
  boost_decimal b3(10);
  auto b4(b2 / b3); // честный 0.1
  ::std::cout << ::std::setprecision(80) << b4 << ::std::endl;
  auto s2(b4+b4+b4+b4+b4+b4+b4+b4+b4+b4);
  ::std::cout << "sum2 " << ::std::setprecision(80) << s2 << ::std::endl;
  assert(s2==1);
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[2]: [c++][decimal] boost.multiprecision не работает
От: anatoly1  
Дата: 19.10.15 12:29
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Это норма.


Я в курсе, что с double буде точно так же. Для того decimal и использую, чтобы проблему решить. decimal32 нормально же работает.

PS

Выяснил, что если проинициализировать так:
boost_decimal b("0.1");

то при сравнении будет true. Но подобный подход не устраивает.
Re[3]: [c++][decimal] boost.multiprecision не работает
От: WiseAlex Беларусь  
Дата: 19.10.15 12:51
Оценка:
Здравствуйте, anatoly1, Вы писали:
A>Я в курсе, что с double буде точно так же. Для того decimal и использую, чтобы проблему решить. decimal32 нормально же работает.

сам себе и ответил.

если брать за начальное значение число в double которое в нем точно представить нельзя то и результат будет соответсвующим...
как вариант
boost_decimal b(1);
b /= 10;
Re[3]: [c++][decimal] boost.multiprecision не работает
От: uzhas Ниоткуда  
Дата: 19.10.15 13:33
Оценка: 2 (1)
Здравствуйте, anatoly1, Вы писали:

A>Для того decimal и использую, чтобы проблему решить. decimal32 нормально же работает.


decimal32 поддерживает 7 десятичных цифр, он округлил входящий double и все получилось красиво, хвост пропал. вики: https://en.wikipedia.org/wiki/Decimal32_floating-point_format
cpp_dec_float_50 поддерживает 50 десятичных цифр, он достаточно точно переварил кучу знаков после запятой. в итоге получилось не 0.1
отсюда и разное поведение

как вариант, я бы предложил найти метод округления в cpp_dec_float_50 под нужную точность и задействовать его. с этими классами не работал, так что не подскажу как это сделать и возможно ли это в принципе
Отредактировано 19.10.2015 14:26 uzhas . Предыдущая версия . Еще …
Отредактировано 19.10.2015 13:35 uzhas . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.