Мне нужна функция, которая снижает точность (количество цифр) моих двойников.
Мне это нужно для расчета, а не для вывода на экран.
То, что я до сих пор, это:
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
_number *= tenth;
_number = floor(_number);
_number /= tenth;
return _number;
}
призвание setDigits(sqrt(2),3)
дает 1.4139999999999999, а не 1.414, как я хочу.
Что я могу сделать?
Что я могу сделать?
К сожалению, ничего для основной проблемы: в вашей платформе 1.414 не имеет точного двойного представления. Вы не можете выполнить вычисление с «1,414», потому что вы не можете разместить «1,414» в любом месте ваш double
,
Смотри например http://www3.ntu.edu.sg/home/ehchua/programming/java/DataRepresentation.html .
Что ты Можно сделать, чтобы сохранить ваш номер с максимальной точностью, и дисплей это с пониженной точностью. Вам необходимо рассчитать точность станка и отслеживать ошибки во время вычислений.
Таким образом, вы будете использовать 1.413999999999997 и в конце получите ответ, скажем, 41.99999137; с которым вы будете отображать
printf("The answer is %.3f\n", theAnswer);
Или вы можете изменить платформу (компилятор, или математическую библиотеку, или представление с плавающей запятой, например, использовать long double
где поддерживается), но помните, что тогда вы можете получить 1.414 прямо по цене, скажем, 1.873 неправильно (пусть это будет 1.87299999999 или 1.87300000001), и в вычислениях будут примерно такие же ошибки.
Вы можете работать в целочисленной арифметике, умножая начальные числа на 1 000 000 (и получая 1414 000) или другую подходящую шкалу, а затем деля в конце. Целые числа имеют максимальный предел, хотя.
Существуют также библиотеки произвольной точности, которые используют другое внутреннее представление и позволяют вам указывать точность так, как вы хотите, например, GMP ( http://gmplib.org/ ). Конечно, работать с этим сложнее, чем указывать
op1 = 6.0;
op2 = 7.0;
theAnswer = op1 * op2;
и обработка также идет медленнее, но результаты хороши — или так хороши, как вы говорите им.
Следующие строки недействительны.
double tenth = pow((double)10,_decimals); //_decimals is not declared
_number = floor(_digits); //should be floor(_number)
Исправленная функция
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
_number *= tenth;
_number = floor(_number);
_number /= tenth;
return _number;
}
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
int result = (_number * tenth) + 0.5;
double aux = result / tenth;
return aux;
}
Попробуй это. Для вашего примера за десятый = 1000;
result = 1413,9999999999999 * 1000 +0,5
result = 1414,4......
result = 1414
я не знаю, вы не можете проверить этот ответ, но другие делают
Я новичок в C ++, но я нашел способ сделать это
double Point::norm()
{
return (double)floor((sqrt(pow(px,2)+pow(py,2)+pow(pz,2))*1000))*0.001;
}
Я использую это, но вы можете написать свой собственный класс математики, чтобы сделать это для вас
Попробуй это:
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
return floor(_number * tenth + 0.5)/tenth;
}
std::cout<<setDigits(sqrt(2),3);
Output: 1.414
Вы можете создать промежуточный класс, который управляет данными внутри int
, но входы и выходы как double
:
class TruncatedDouble
{
private:
int value_;
public:
TruncatedDouble(double d) : value_((int)(double * 1000)) {}
void SetValue(double d) {value_ = (int)(double * 1000);}
double GetValue() {return (double)value_ / 1000;}
};
Вы также должны перегружать все обычные операторы, но это легко. Пример:
TruncatedDouble& operator+=(const TruncatedDouble& rh) {value_ += rh.value_;}
И так далее. Этот класс будет довольно быстрым, так как вы работаете с int
вместо double
и вы никогда не потеряете точность.