В настоящее время я работаю над кодом C ++, в котором мне нужно прочитать данные из базы данных, и если значение базы данных не равно нулю, мне нужно применить некоторую дополнительную логику.
Но в базе данных есть значения, которые рассчитываются и могут быть получены в виде -0.0
, И этот отрицательный ноль рассматривается как значение мусора в двойной переменной C ++. Я уже инициализировал значение как 0.0
в конструкторе.
Образец кода:
for(Sample::List<BalanceSheet>::Iterator i((Sample::List<BalanceSheet> &) Balance.Entries()); i.HaveItem(); ++i) // This list is being populated from Database
{
if (SomeCondition != "")
{
if (i->GetBalance() != 0) // This is where am getting Garbage values since GetBalance() returns -0.0
{
DoOperation();
}
}
}
-0.0
совершенно допустимое значение для double
, Проблема в том, что вы сравниваете двойные числа по неравенству.
Что вы должны сделать, это что-то вроде этого:
i->GetBalance() > std::numeric_limits<double>::epsilon()
Во-первых, вы должны никогда использовать ==
или же !=
с переменными с плавающей точкой. По сути, это бессмысленные операции, поскольку ограничения типов с плавающей запятой означают, что даже, казалось бы, безобидные значения могут не сравниваться одинаково. Вполне возможно, что 2 + 2 не 4, по крайней мере, насколько ==
определил бы это.
Настоящая проблема здесь заключается в том, что вы используете знак «нулевого» значения, которое, как указано выше, в действительности не может быть точно нулевым, во-первых, но, что более важно, его сложно проверить с помощью стандартных операторов сравнения. Смотрите этот связанный вопрос для некоторого обсуждения.
Лучшее решение для этого, если у вас есть доступ к C ++ 11 или поддерживающему его компилятору, это использовать copysign
согласно ответу Влада на этот вопрос. Эта функция принимает 2 параметра. Первый представляет величину возвращаемого значения, а второй знак. Вот пример:
#include "iostream"#include <math.h>
using namespace std;
int main()
{
double posZero = +0.0d;
double negZero = -0.0d;
if( copysign( 1, posZero ) < 0 )
{
cout << "posZero is negative\n";
}
else
{
cout << "posZero is positive\n";
}
if( copysign( 1, negZero ) < 0 )
{
cout << "negZero is negative\n";
}
else
{
cout << "negZero is positive\n";
}
}
posZero положительный
NegZero отрицательный
В этом примере copysign
создает значение +/- 1 в соответствии со знаком второго аргумента. Первым аргументом для ваших целей может быть любое ненулевое значение, но также может быть и 1.
В качестве альтернативы, вы можете использовать signbit, что, честно говоря, вероятно, более прямой. Версия выше с использованием этой функции:
#include "iostream"#include <math.h>
using namespace std;
int main()
{
double posZero = +0.0d;
double negZero = -0.0d;
if( signbit( posZero ) )
{
cout << "posZero is negative\n";
}
else
{
cout << "posZero is positive\n";
}
if( signbit( negZero ) )
{
cout << "negZero is negative\n";
}
else
{
cout << "negZero is positive\n";
}
}
С таким же выходом.