C++ - оператор If все еще выполняется при сравнении удвоений

В этом проекте я должен создать класс Polynomial. Вот что у меня есть для файла Polynomial.cpp:

#include <iostream>
#include "Polynomial.h"
#include <stdexcept>
#include <iomanip>
#include <cmath>
#include <string>

using namespace std;

Polynomial::Polynomial(double c[], int size){ 
    set(c,size);
}

Polynomial::Polynomial(const Polynomial &poly){
    size = poly.size;
    c = new double[size];
    for(int i=0; i<size; i++){
        c[i] = poly.c[i];
    }
}

Polynomial::~Polynomial(){
    delete [] c;
}

void Polynomial::set(double ca[], int s){
    if (s < 1){
        throw std::invalid_argument("Size must be larger or equal to 1.");
    }
    else{
        size = s;
        c = new double[size];
        for(int i=0; i<size; i++){
            c[i] = ca[i];
        }
    }
}

double* Polynomial::getPointer() const{
    return c;
}

int Polynomial::getSize() const{
    return size;
}

bool Polynomial::operator ==(const Polynomial& poly) const{
    if (size != poly.size){
        return false;
    }
    int i = 0;
    int count = 0;
    while ( i < size ) {
        if ( c[i] == poly.c[i] ) {
            count++;
        }
        i++;
    }
    if ( count != size) {
        return false;
    }
    return true;
}

Polynomial Polynomial::operator +(const Polynomial& poly) const{
    int d = fabs(size - poly.size); //absolute value of size difference
    int bigger = size; //the size of the bigger polynomial
    int smaller = poly.size; //the size of the smaller polynomial
    if ( poly.size > size) {
        bigger = poly.size;
        smaller = size;
    }
    double r[bigger];
    double s[bigger];  //new coef array for the smaller polynomial with zeros coefs added

    if ( d != 0 ) {
        if (smaller = poly.size){
            for(int i=0; i < smaller; i++){
                s[i] = poly.c[i];
            }
            for(int i=smaller; i < bigger; i++){
                s[i] = 0;
            }
            for(int i=0; i < bigger; i++){
                r[i] = c[i] + s[i];
            }
        }
        else{
            for(int i=0; i < smaller; i++){
                s[i] = c[i];
            }
            for(int i=smaller; i < bigger; i++){
                s[i] = 0;
            }
            for(int i=0; i < bigger; i++){
                r[i] = poly.c[i] + s[i];
            }
        }
    }
    else {
        for ( int i = 0; i < bigger; i++) {
            r[i] = c[i] + poly.c[i];
        }
    }

    return Polynomial(r,bigger);
}

ostream& operator<<(ostream &lhs, const Polynomial &poly){
    string plus = "+";
    bool valid = false; //check if the first term of the polynomial to be printed is valid or not, valid is true when term is non-zero

if (poly.getPointer()[poly.getSize()-1] < 0){
    if (poly.getPointer()[poly.getSize()-1] != 0){
        lhs << setprecision(1) << fixed << poly.getPointer()[poly.getSize()-1] << "x^" << poly.getSize()-1 << " ";
    }
    for(int i=poly.getSize()-2; i >= 0; i--){
        if (poly.getPointer()[i] != 0 && i != 1 && i != 0){
            if (poly.getPointer()[i] > 0){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i] << "x^" << i << " ";
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i] << "x^" << i << " ";
            }
        }
        else if (poly.getPointer()[i] != 0 && i == 1){
            if (poly.getPointer()[i] > 0){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i] << "x" << " ";
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i] << "x" << " ";
            }
        }
        else if (poly.getPointer()[i] != 0 && i == 0){
            if (poly.getPointer()[i] > 0){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i];
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i];
            }
        }
    }
}
else{
    if (poly.getPointer()[poly.getSize()-1] != 0){
        lhs << setprecision(1) << fixed << noshowpos << poly.getPointer()[poly.getSize()-1] << "x^" << poly.getSize()-1 << " ";
        valid = true;
    }
    for(int i=poly.getSize()-2; i >= 0; i--){
        if (poly.getPointer()[i] != 0 && i != 1 && i != 0){
            if (poly.getPointer()[i] > 0 && valid == true){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i] << "x^" << i << " ";
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i] << "x^" << i << " ";
                valid = true;
            }
        }
        else if (poly.getPointer()[i] != 0 && i == 1){
            if (poly.getPointer()[i] > 0 && valid == true){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i] << "x" << " ";
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i] << "x" << " ";
                valid = true;
            }
        }
        else if (poly.getPointer()[i] != 0 && i == 0){
            if (poly.getPointer()[i] > 0 && valid == true){
                lhs << setprecision(1) << fixed << plus << poly.getPointer()[i];
            }
            else{
                lhs << setprecision(1) << fixed << poly.getPointer()[i];
                valid = true;
            }
        }
    }
}
return lhs;

}

Вот моя тестовая программа:

#include <iostream>
#include "Polynomial.h"
#include <iomanip>

using namespace std;

int main() {
double c[] = {0,-5,3};
double d[] = {3,0,-5,0};

Polynomial p1(c,3);
Polynomial p2(d,4);
cout << "Polynomial p1 is: " << p1 << endl;
cout << "Degree of polynomial p1 is: " << noshowpos << p1.getDegree() << endl;
cout << "Polynomial p2 is: " << p2 << endl;

Polynomial p3(p1);
cout << "Polynomial p3 now is equal to p1 after copy constructor: " << p3 << endl;

bool same = p1 == p3;
cout << "Is p1 equal to p3? " << noshowpos << same << endl;

Polynomial p4 = p1 + p2;
cout << "Polynomial p4 is the sum of p1 and p2: " << p4 << endl;

Итак, проблема, с которой я столкнулся, связана с этим выражением if:

if (poly.getPointer()[poly.getSize()-1] != 0){
    lhs << setprecision(1) << fixed << poly.getPointer()[poly.getSize()-1] << "x^" << poly.getSize()-1 << " ";
}

Когда я выполняю оператор + для p4 = p1 + p2, полиномиальный массив double для p4 равен [3, -5, -2, 0]. Таким образом, последнее значение p4 [size - 1] этого массива равно 0. Как вы можете видеть выше в операторе if, когда я получаю значение poly.getPointer () [poly.getSize () - 1], оно равно 0; однако, когда я сравниваю его с нулем в операторе if, он все равно выполняется, даже если оператор if ложен (0 не равно 0, поэтому этот оператор if следует пропустить). Я пробовал запускать его как в среде IDE, так и на движке Linux; однако результат все тот же. Я не уверен, связано ли это с этим конструктором, который вызывает метод set:

Polynomial::Polynomial(double c[], int size){ 
    set(c,size);
}

void Polynomial::set(double ca[], int s){
    if (s < 1){
        throw std::invalid_argument("Size must be larger or equal to 1.");
    }
    else{
        size = s;
        c = new double[size];
        for(int i=0; i<size; i++){
            c[i] = ca[i];
        }
    }
}

Пожалуйста помоги. Спасибо.

Вы не можете сравнивать значения с плавающей запятой для точного равенства на компьютерах. См., Например, Математика с плавающей запятой не работает? для некоторых деталей

Some programmer dude 17.11.2018 06:15

@Someprogrammerdude Если вы не можете сравнивать значения, вы также можете выполнять вычисления.

curiousguy 17.11.2018 15:18

@curiousguy Сравнения для точное равенство Я сказал. Сравнения в целом (например, больше / меньше или равенство с эпсилоном) просто прекрасны. Что касается вычислений, чем больше их вы выполняете со значениями с плавающей запятой, тем более неточными они становятся.

Some programmer dude 17.11.2018 15:33

@Someprogrammerdude Если вы не можете сравнить на равенство, компилятор сломан. Так что сравнивать нельзя вообще.

curiousguy 17.11.2018 15:35

@curiousguy Хорошо, я не говорю, что нельзя сравнивать использование == со значениями с плавающей запятой, или что компилятор не разрешает это или что-то в этом роде. Я говорю, что это бессмысленно, поскольку значения с плавающей запятой имеют тенденцию терять точность после нескольких вычислений из-за ошибок округления, и то, что вы можете подумать, 12.345 может не быть точно12.345. Это делает сравнения с использованием ==бессмысленно, поскольку казаться редко работает так, как думают новички.

Some programmer dude 17.11.2018 15:39

@Someprogrammerdude Сравнение на равенство должен делает то, что обычно делает, то есть проверяет, является ли одно значение копией другого, или два значения были получены одними и теми же вычислениями на основе одних и тех же значений, или два значения, используемые в одном и том же "обычном" вычислении. даст тот же результат.

curiousguy 17.11.2018 15:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
677
0

Другие вопросы по теме