2012-05-02 3 views
3

В моем предыдущем вопросе Comparing a double and int, without casting or conversion я узнал, как разница между двумя удвоениями отключала сравнение.Как установить точность при использовании типа double/float в C++

Я пришел по методу setprecision(), который поможет отображать все числа после десятичной.

Таким образом, разница в 6.15 и 3.15 Было установлено, что: 3,00000000000000044408920985006

Теперь, когда он получает по сравнению с 3, он возвращает результат говорят, что это больше, чем 3.

Как заставить он должен принимать только ограниченное число цифр?

Когда я 6.1 и 3.1, разница была: 2,99999999999999955591079014994

Как я должен сделать точность, так что мы знаем, что это на самом деле равно 3, и не менее.

+3

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

ответ

4

Надеюсь, вы должны знать, что плавающий/двойной не может быть точно представлен в двоичном формате, а усечение происходит из-за повторяющегося десятичного числа. Ваше сравнение с float/double с целым числом всегда будет терпеть неудачу.

Даже ваш метод setprecision не будет работать, потому что его метод iomanip позволяет установить точность отображения, а не сохраненное значение.

Портативный способ сравнения двойников не использовать оператор «==», но сделать что-то вроде

bool Compare(double a,double b) { 
    std::fabs(a - b) < std::numeric_limits<double>::epsilon(); 
} 

Вы можете использовать это, чтобы сравнить двойной с поплавком и или целым числом. Вы также можете написать подобную функцию сравнения для поплавка

bool Compare(float a,float b) { 
    std::fabs(a - b) < std::numeric_limits<float>::epsilon(); 
} 
+2

Значения эпсилона подходят только в том случае, если значения, которые вы сравниваете, близки к 1.0. –

+0

Я думаю, что это должно быть abs (a-b) <= epsilon. вместо < – schwiz

1

setprecision позволяет выбрать количество цифр, которые вы выплевываете в поток. Он не определяет количество цифр, которые необходимо учитывать. Для округления используйте одну из функций округления от <cmath>.

3

В комментарии на ваш другой вопрос, вы уже указывали на this great paper на числах с плавающей точкой. Это хорошо стоит прочитать.

В отношении вашего конкретного вопроса стандартным способом является определение допуска , с которым должно производиться сравнение между парными. Например, если у вас есть два двухместных a и b, и хотите, чтобы определить, является ли a больше b в пределах допуска eps (еще дважды), вы могли бы сделать что-то вроде:

if (a - b > eps) { 
    // a is greater than b 
} else { 
    // a is not greater than b 
} 

В качестве альтернативы, если вы хотите знаю, что a равно b в пределах допуска, указанный eps, вы могли бы сделать что-то в этом роде:

if (std::abs(a - b) <= eps) { 
    // a and b are equal within the set tolerance 
} else { 
    // a and b are not equal within the set tolerance 
} 

Как указывалось другими, C++ поставляется с некоторыми полезными функциями, выполненными из для выполнения подобных сравнений. Посмотрите на std::abs, std::numeric_limits и this nice post на SO.

+0

Вы должны быть осторожны, определяя допуск 'eps'. Возможно, вы захотите использовать [относительную ошибку] ​​(http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm). – mgiuffrida

2

Вот функция сравнения, которая определяет, находятся ли два числа в пределах одного LSB друг от друга.

bool Compare(double a, double b) 
{ 
    return (a <= std::nextafter(b, abs(1.1*b))) && (b <= std::nextafter(a, abs(1.1*a))); 
} 

std::nextafter является новым для C++ 11, но версии доступны в более ранних компиляторов. См. Generate next largest or smallest representable floating point number without bit twiddling

0

Отсутствие цифр точности в поплавке и двойном действии фактически зависит от их размера соответственно. Именно поэтому плавать обычно имеет меньшую точность, чем двойное. Вы можете использовать

std::cout<<std::setprecision(desired no); 

    float a=(desired no); 

Теперь вы успешно установить точность float.The же можно сделать для другого типа соответствующих данных, включая двойной, а также. Предупреждение не устанавливает точность, превышающую то, что может предложить тип данных. Двойной имеет от 15 до 18 цифр точности, в то время как поплавок имеет только от 6 до 9 цифр точности.

Смежные вопросы