01 复数类

01 复数类


作者:abnb250/山中鹤鸣
博客:https://www.cnblogs.com/abnb250
交流群:1062464078
点击返回目录



前情提要

这一节实现一个 Complex 类,覆盖四则运算、+= 系列、共轭、模长、比较、流输入输出,重点是运算符重载的形态与返回值约定。
注释版主要盯三处:
operator*=/operator/= 若把公式内联展开,实部先更新会让虚部算错;
operator== 用 eps 而非 ==,否则浮点误差误判;
operator>> 先读到局部变量再提交,避免第二个数读失败时对象处于半更新状态。



代码(加注释版)

注释解释了两种场景:

  1. 代码有反直觉痕迹,自然写法就在旁边。
  2. 代码看起来自然,但背后有隐形决策。

Complex.h

#ifndef COMPLEX_H
#define COMPLEX_H

#include <iostream>
#include <algorithm>
#include <cmath>

class Complex{
private:
    double real;
    double imag;
public:
    Complex(): real(0), imag(0) {}
    Complex(double re, double im) : real(re), imag(im) {}
    double get_re() const;
    double get_im() const;
    Complex& set_re(double newre);
    Complex& set_im(double newim);
    Complex operator+(const Complex& b) const;
    Complex operator-(const Complex& b) const;
    Complex operator*(const Complex& b) const;
    Complex operator/(const Complex& b) const;
    Complex operator/(const double& b) const;
    Complex& operator+=(const Complex& b);
    Complex& operator-=(const Complex& b);
    Complex& operator*=(const Complex& b);
    Complex& operator/=(const Complex& b);
    Complex get_conj() const;
    double get_abs() const;
    bool operator==(const Complex& b) const;
    bool operator!=(const Complex& b) const;
    friend Complex operator+(double a, const Complex& b);
    friend std::ostream& operator<<(std::ostream& os, const Complex& a);
    friend std::istream& operator>>(std::istream& is, Complex& a);
};

#endif

Complex.cpp

#include "complex.h"

double Complex::get_re() const {
    return real;
}

double Complex::get_im() const {
    return imag;
}

Complex& Complex::set_re(double newre){
    real = newre;
    return *this;
}

Complex& Complex::set_im(double newim){
    imag = newim;
    return *this;
}

Complex Complex::operator+(const Complex& b) const {
    Complex res(real + b.real, imag + b.imag);
    return res;
}
Complex Complex::operator-(const Complex& b) const {
    Complex res(real - b.real, imag - b.imag);
    return res;
}
Complex Complex::operator*(const Complex& b) const {
    double tmp1, tmp2;
    tmp1 = real*b.real - imag*b.imag;
    tmp2 = real*b.imag + imag*b.real;
    Complex res(tmp1, tmp2);
    return res;
}
Complex Complex::operator/(const Complex& b) const {
    Complex b_(b.real, -b.imag);
    Complex son = *this *b_;
    Complex fa = b*b_;
    double tmp = fa.real;
    if(tmp == 0){
        std::cout << "/ is error " << '\n';
        return *this;
    }
    Complex res(son.real/tmp, son.imag/tmp);
    return res;
}

Complex Complex::operator/(const double& b) const{
    if(b == 0) {
        std::cout << "b == 0" << '\n';
        return *this;
    }
    Complex res(real/b, imag/b);
    return res;
}

Complex& Complex::operator+=(const Complex& b){
    real += b.real;
    imag += b.imag;
    return *this;
}

Complex& Complex::operator-=(const Complex& b){
    real -= b.real;
    imag -= b.imag;
    return *this;
}

Complex& Complex::operator*=(const Complex& b){
    // 不能就地写 real = real*b.real - imag*b.imag; 再 imag = real*b.imag + imag*b.real;
    // 第二条会用到已更新的 real,虚部算错
    Complex tmp = *this *b;
    real = tmp.real;
    imag = tmp.imag;
    return *this;
}

Complex& Complex::operator/=(const Complex& b){
    // 同 operator*=:若内联展开,实部先更新会让虚部计算用到新实部
    Complex tmp = *this /b;
    real = tmp.real;
    imag = tmp.imag;
    return *this;
}

Complex Complex::get_conj() const{
    return Complex(real, -imag);
}

double Complex::get_abs() const{
    return std::sqrt(real*real + imag*imag);   
}

bool Complex::operator==(const Complex& b) const{
    // 不能改成 real == b.real && imag == b.imag,浮点误差会让数学相等的值判为不等
    double eps = 1e-9;
    if(std::abs(real - b.real) > eps) return false;
    if(std::abs(imag - b.imag) > eps) return false;
    return true;
}

bool Complex::operator!=(const Complex& b) const{
    if(*this == b) return false;
    return true;
}

Complex operator+(double a, const Complex& b){
    Complex tmp(a+b.real, b.imag);
    return tmp;
}

std::ostream& operator<<(std::ostream& os, const Complex& a){
    if(a.real != 0 && a.imag != 0){
        if(a.imag > 0)
            os << a.real << '+' << a.imag << 'i';
        else
            os << a.real << a.imag << 'i';
        return os;
    }
    if(a.real == 0 && a.imag != 0){
        os << a.imag << 'i';
        return os;
    }
    if(a.real != 0 && a.imag == 0){
        os << a.real;
        return os;
    }
    if(a.real == 0 && a.imag == 0){
        os << 0;
        return os;
    }
    return os;
}

std::istream& operator>>(std::istream& is, Complex& a){
    double re, im;
    // 不能直接 is >> a.real >> a.imag,第二个读取失败时 a 的 real 已改、imag 未改
    if(is >> re >> im){
        a.real = re;
        a.imag = im;
    }
    return is;
}








posted @ 2026-11-01 17:34  abnb250  阅读(6)  评论(0)    收藏  举报