2015-11-30 2 views
0

У меня есть код, чтобы сравнить два класса дробей, мои операторы класса нижеДробь Булевы операторы

// Equal to (==) 
     bool Fraction::operator == (const Fraction &fraction){ 
      if (static_cast<double>(numerator/denominator) == static_cast<double>(fraction.numerator/fraction.denominator)){ 
       return true; 
      } else { 
       return false; 
      } 
     } // End of == operator 
. 
. 
. 
. // And so on for all other comparisons 

Однако мой выход возвращает операторов (==), (< =) и (> =), говоря, что все они верны.

В моей основной()

// EQUAL TO 
     if (fraction1 == fraction2){ 
      cout << fraction1.toString() << " is equal to " << fraction2.toString() << "." << endl; 
     } 
. 
. 
. // And so on... 

Я также попытался if (fraction1.operator==(fraction2)){ вместо if (fraction1 == fraction2) но они оба возвращают то же самое. Я застрял на этом, может быть, что-то не так с моей логикой? При необходимости я могу отправить больше кода. Благодаря!

Редактировать: static_cast должно быть двойным. Числители и знаменатели являются целыми числами, а в моих методах сеттера и геттера они являются целыми числами.

+5

Конечно основная математика бы предположить, что условие равенства 'a.numerator * b.denominator == a.denominator * b.numerator', без разделения, учитывая, что это * определение * рационального число? –

+4

Кроме того, почему 'double' с одной стороны и' float' с другой? –

+4

Если числитель и знаменатель являются int, вы можете столкнуться с целыми делениями. Вы должны бросить в floats/doubles * before * diving (или просто использовать технику умножения выше). – IanPudney

ответ

1

Если numerator меньше, чем denominator для всех экземпляров класса, которые вы используете в вызове oparator==(), numerator/denominator будет равен нуль из-за целочисленное деление.

В этом случае

if (static_cast<double>(numerator/denominator) == static_cast<float>(fraction.numerator/fraction.denominator)){ 

эквивалентно:

if (static_cast<double>(0) == static_cast<float>(0)){ 

который будет true.

Если ваши номера не слишком велики, т.е.нет никакого риска integer overflow, вы можете использовать:

if (this->numerator*fraction.denominator == fraction.numerator*this->denominator) 

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

double f1 = 1.0*numerator/denominator; 
double f2 = 1.0*fraction.numerator/fraction.denominator; 

if (fabs(f1-f2) < **SOME TOLERANCE VALUE**) 
+0

Разве терпимость не делает это * хуже * на этот раз? Тест должен быть как можно точнее после всех – harold

+0

@harold, это решение, которое должен сделать OP. При сравнении чисел с плавающей запятой я обнаружил, что обычно имеет смысл сравнивать их в пределах допуска. –

+0

Потому что обычно возникают ошибки округления. На этот раз нет. – harold

1
if (static_cast<double>(numerator/denominator) == static_cast<float>(fraction.numerator/fraction.denominator)){ 

Первый вопрос здесь заключается в том, что на одном вы бросаете плавать и другие отливки, чтобы удвоить. Это почти наверняка не то, что вы хотите, во-первых, вы должны использовать тот же тип данных для обеих вещей, которые вы сравниваете. Хотя в этом случае это может работать, из-за ошибки, о которой я расскажу ниже, вы не хотите напрямую сравнивать числа с плавающей запятой, прочитайте это https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/02Numerics/Double/paper.pdf для получения дополнительной информации о подводных камнях этого.

Большая проблема, которую я вижу в том, что у вас есть целое DIV происходит, и это, скорее всего, взрывать плохо в некоторых случаях, возьмем для примера этот случай, когда код не:

int numerator1 = 5; 
int denominator1 = 2; 
int numerator2 = 4; 
int denominator2 = 2; 

В этом случае вы в основном получаете:

numerator1/denominator1 == numerator2/denominator2 

Что, вероятно, не, что вы хотели. Вы можете увидеть это в действии здесь http://coliru.stacked-crooked.com/a/0eb3723f952fbf4a

Предположив, что вы храните числитель и знаменатель в виде целых чисел, то вы можете избежать всех чисел с плавающей точкой в ​​тестировании равенства, сохраняя все, как целые числа, выполнив:

if (numerator * fraction.denominator == fraction.numerator * denominator){ 
    return true; 
}else{ 
    return false; 
} 

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

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