2014-02-19 2 views
0

Я написал эту функцию рекурсивно круглые в double до N цифр:C++ этаж() уменьшается значение 1

double RoundDouble(double value, unsigned int digits) 
{ 
    if (value == 0.0) 
     return value; 
    string num = dtos(value); 
    size_t found = num.find("."); 
    string dec = ""; 
    if (found != string::npos) 
     dec = num.substr(found + 1); 
    else 
     return value; 
    if (dec.length() <= digits) 
    { 
     LogToFile("C:\\test.txt", "RETURN: " + dtos(value) + "\n\n\n"); 
     return value; 
    } 
    else 
    { 
     double p10 = pow(10, (dec.length() - 1)); 
     LogToFile("C:\\test.txt", "VALUE: " + dtos(value) + "\n"); 
     double mul = value * p10; 
     LogToFile("C:\\test.txt", "MUL: " + dtos(mul) + "\n"); 
     double sum = mul + 0.5; 
     LogToFile("C:\\test.txt", "SUM: " + dtos(sum) + "\n"); 
     double floored = floor(sum); 
     LogToFile("C:\\test.txt", "FLOORED: " + dtos(floored) + "\n"); 
     double div = floored/p10; 
     LogToFile("C:\\test.txt", "DIV: " + dtos(div) + "\n-------\n"); 
     return RoundDouble(div, digits); 
    } 
} 

Но из файла журнала, то действительно странное происходит с полом() в некоторых случаях ...

Вот выходной пример хорошего расчета:

VALUE: 2.0108 
MUL: 2010.8 
SUM: 2011.3 
FLOORED: 2011 
DIV: 2.011 
------- 
VALUE: 2.011 
MUL: 201.1 
SUM: 201.6 
FLOORED: 201 
DIV: 2.01 
------- 
RETURN: 2.01 

А вот выход пример плохого расчета:

VALUE: 67.6946 
MUL: 67694.6 
SUM: 67695.1 
FLOORED: 67695 
DIV: 67.695 
------- 
VALUE: 67.695 
MUL: 6769.5 
SUM: 6770 
FLOORED: 6769 <= PROBLEM HERE 
DIV: 67.69 
------- 
RETURN: 67.69 

Не пол (6770) должен возвращать 6770? Почему он возвращает 6769?

+10

Потому что это не на самом деле 6770, а нечто очень близкое к нему. [Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) –

+1

«Не должен быть этаж (6770) 6770?» Это неверно для небольших значений 6770. – user2079303

+0

Попробуйте добавить значение эпсилона на пол, это похоже на то, что значение действительно 6769 с десятичными знаками, что делает его близким к 6770. –

ответ

0

Итак, прежде всего, спасибо всем за предложения. Кстати, на данный момент решение «double to string -> string to double -> floor» кажется единственным, дающим точно ожидаемый результат. Поэтому я просто нужно заменить:

double floored = floor(sum); 

с

double floored = floor(stod(dtos(sum))); 

Если у кого есть лучшее решение, пожалуйста, разместить его.