Rust 重载运算符|复数结构的“加减乘除”四则运算

这篇具有很好参考价值的文章主要介绍了Rust 重载运算符|复数结构的“加减乘除”四则运算。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Rust 重载运算符|复数结构的“加减乘除”四则运算,Rust,算法,rust

复数

基本概念

复数定义

由实数部分和虚数部分所组成的数,形如a+bi 。

其中a、b为实数,i 为“虚数单位”,i² = -1,即虚数单位的平方等于-1。

a、b分别叫做复数a+bi的实部和虚部。

当b=0时,a+bi=a 为实数;
当b≠0时,a+bi 又称虚数;
当b≠0、a=0时,bi 称为纯虚数。

实数和虚数都是复数的子集。如同实数可以在数轴上表示一样复数也可以在平面上表示,复数x+yi以坐标点(x,y)来表示。表示复数的平面称为“复平面”。

复数相等

两个复数不能比较大小,但当个两个复数的实部和虚部分别相等时,即表示两个复数相等。

共轭复数

如果两个复数的实部相等,虚部互为相反数,那么这两个复数互为共轭复数。

复数的模

复数的实部与虚部的平方和的正的平方根的值称为该复数的模,数学上用与绝对值“|z|”相同的符号来表示。虽然从定义上是不相同的,但两者的物理意思都表示“到原点的距离”。

复数的四则运算

加法(减法)法则

复数的加法法则:设z1=a+bi,z2 =c+di是任意两个复数。两者和的实部是原来两个复数实部的和,它的虚部是原来两个虚部的和。两个复数的和依然是复数。

即(a+bi)±(c+di)=(a±c)+(b±d)

乘法法则

复数的乘法法则:把两个复数相乘,类似两个多项式相乘,结果中i²=-1,把实部与虚部分别合并。两个复数的积仍然是一个复数。

即(a+bi)(c+di)=(ac-bd)+(bc+ad)i

除法法则

复数除法法则:满足(c+di)(x+yi)=(a+bi)的复数x+yi(x,y∈R)叫复数a+bi除以复数c+di的商。

运算方法:可以把除法换算成乘法做,将分子分母同时乘上分母的共轭复数,再用乘法运算。

即(a+bi)/(c+di)=(a+bi)(c-di)/(c*c+d*d)=[(ac+bd)+(bc-ad)i]/(c*c+d*d)

复数的Rust代码实现

结构定义

Rust语言中,没有像python一样内置complex复数数据类型,我们可以用两个浮点数分别表示复数的实部和虚部,自定义一个结构数据类型,表示如下:

struct Complex {
    real: f64,
    imag: f64,
}

示例代码:

#[derive(Debug)]
struct Complex {
    real: f64,
    imag: f64,
}

impl Complex {  
    fn new(real: f64, imag: f64) -> Self {
        Complex { real, imag }  
    }
}

fn main() {  
    let z = Complex::new(3.0, 4.0);
    println!("{:?}", z);
    println!("{} + {}i", z.real, z.imag);
}

注意:#[derive(Debug)] 自动定义了复数结构的输出格式,如以上代码输出如下:

Complex { real: 3.0, imag: 4.0 }
3 + 4i

重载四则运算

复数数据结构不能直接用加减乘除来做复数运算,需要导入标准库ops的运算符:

use std::ops::{Add, Sub, Mul, Div, Neg};

Add, Sub, Mul, Div, Neg 分别表示加减乘除以及相反数,类似C++或者python语言中“重载运算符”的概念。

根据复数的运算法则,写出对应代码:

fn add(self, other: Complex) -> Complex {
    Complex {
        real: self.real + other.real,
        imag: self.imag + other.imag,
    }  
}  

fn sub(self, other: Complex) -> Complex {
    Complex {  
        real: self.real - other.real,
        imag: self.imag - other.imag,
    }  

fn mul(self, other: Complex) -> Complex {  
    let real = self.real * other.real - self.imag * other.imag;
    let imag = self.real * other.imag + self.imag * other.real;
    Complex { real, imag }  
}  

fn div(self, other: Complex) -> Complex {
    let real = (self.real * other.real + self.imag * other.imag) / (other.real * other.real + other.imag * other.imag);
    let imag = (self.imag * other.real - self.real * other.imag) / (other.real * other.real + other.imag * other.imag);
    Complex { real, imag }
}

fn neg(self) -> Complex {
    Complex {
        real: -self.real,
        imag: -self.imag,
    }
}

Rust 重载运算的格式,请见如下示例代码:

use std::ops::{Add, Sub, Mul, Div, Neg};

#[derive(Clone, Debug, PartialEq)]
struct Complex {
    real: f64,
    imag: f64,
}

impl Complex {  
    fn new(real: f64, imag: f64) -> Self {
        Complex { real, imag }  
    }
  
    fn conj(&self) -> Self {
        Complex { real: self.real, imag: -self.imag }
    }

    fn abs(&self) -> f64 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn abs(z: Complex) -> f64 {
    (z.real * z.real + z.imag * z.imag).sqrt()
}

impl Add<Complex> for Complex {
    type Output = Complex;

    fn add(self, other: Complex) -> Complex {
        Complex {
            real: self.real + other.real,
            imag: self.imag + other.imag,
        }  
    }  
}  
  
impl Sub<Complex> for Complex {
    type Output = Complex;
  
    fn sub(self, other: Complex) -> Complex {
        Complex {  
            real: self.real - other.real,
            imag: self.imag - other.imag,
        }  
    } 
}  
  
impl Mul<Complex> for Complex {
    type Output = Complex;  
  
    fn mul(self, other: Complex) -> Complex {  
        let real = self.real * other.real - self.imag * other.imag;
        let imag = self.real * other.imag + self.imag * other.real;
        Complex { real, imag }  
    }  
}

impl Div<Complex> for Complex {
    type Output = Complex;
  
    fn div(self, other: Complex) -> Complex {
        let real = (self.real * other.real + self.imag * other.imag) / (other.real * other.real + other.imag * other.imag);
        let imag = (self.imag * other.real - self.real * other.imag) / (other.real * other.real + other.imag * other.imag);
        Complex { real, imag }
    }
}  
  
impl Neg for Complex {
    type Output = Complex;
  
    fn neg(self) -> Complex {
        Complex {
            real: -self.real,
            imag: -self.imag,
        }
    }
}

fn main() {  
    let z1 = Complex::new(2.0, 3.0);
    let z2 = Complex::new(3.0, 4.0);
    let z3 = Complex::new(3.0, -4.0);

    // 复数的四则运算
    let complex_add = z1.clone() + z2.clone();
    println!("{:?} + {:?} = {:?}", z1, z2, complex_add);

    let complex_sub = z1.clone() - z2.clone();
    println!("{:?} - {:?} = {:?}", z1, z2, complex_sub);

    let complex_mul = z1.clone() * z2.clone();
    println!("{:?} * {:?} = {:?}", z1, z2, complex_mul);

    let complex_div = z2.clone() / z3.clone();
    println!("{:?} / {:?} = {:?}", z1, z2, complex_div);

    // 对比两个复数是否相等
    println!("{:?}", z1 == z2);
    // 共轭复数
    println!("{:?}", z2 == z3.conj());
    // 复数的相反数
    println!("{:?}", z2 == -z3.clone() + Complex::new(6.0,0.0));

    // 复数的模
    println!("{}", z1.abs());
    println!("{}", z2.abs());
    println!("{}", abs(z3));
}

输出:

Complex { real: 2.0, imag: 3.0 } + Complex { real: 3.0, imag: 4.0 } = Complex { real: 5.0, imag: 7.0 }
Complex { real: 2.0, imag: 3.0 } - Complex { real: 3.0, imag: 4.0 } = Complex { real: -1.0, imag: -1.0 }
Complex { real: 2.0, imag: 3.0 } * Complex { real: 3.0, imag: 4.0 } = Complex { real: -6.0, imag: 17.0 }
Complex { real: 2.0, imag: 3.0 } / Complex { real: 3.0, imag: 4.0 } = Complex { real: -0.28, imag: 0.96 }
false
true
true
3.605551275463989
5
5

示例代码中,同时还定义了复数的模 abs(),共轭复数 conj()。

两个复数的相等比较 z1 == z2,需要 #[derive(PartialEq)] 支持。

自定义 trait Display

复数结构的原始 Debug trait 表达的输出格式比较繁复,如:

Complex { real: 2.0, imag: 3.0 } + Complex { real: 3.0, imag: 4.0 } = Complex { real: 5.0, imag: 7.0 }

想要输出和数学中相同的表达(如 a + bi),需要自定义一个 Display trait,代码如下:

impl std::fmt::Display for Complex {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.imag == 0.0 {
            formatter.write_str(&format!("{}", self.real))
        } else {
            let (abs, sign) = if self.imag > 0.0 {  
                (self.imag, "+" )
            } else {
                (-self.imag, "-" )
            };
            if abs == 1.0 {
                formatter.write_str(&format!("({} {} i)", self.real, sign))
            } else {
                formatter.write_str(&format!("({} {} {}i)", self.real, sign, abs))
            }
        }
    }
}

输出格式分三种情况:虚部为0,正数和负数。另外当虚部绝对值为1时省略1仅输出i虚数单位。

完整代码如下:

use std::ops::{Add, Sub, Mul, Div, Neg};

#[derive(Clone, PartialEq)]
struct Complex {
    real: f64,
    imag: f64,
}

impl std::fmt::Display for Complex {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.imag == 0.0 {
            formatter.write_str(&format!("{}", self.real))
        } else {
            let (abs, sign) = if self.imag > 0.0 {  
                (self.imag, "+" )
            } else {
                (-self.imag, "-" )
            };
            if abs == 1.0 {
                formatter.write_str(&format!("({} {} i)", self.real, sign))
            } else {
                formatter.write_str(&format!("({} {} {}i)", self.real, sign, abs))
            }
        }
    }
}

impl Complex {  
    fn new(real: f64, imag: f64) -> Self {
        Complex { real, imag }  
    }
  
    fn conj(&self) -> Self {
        Complex { real: self.real, imag: -self.imag }
    }

    fn abs(&self) -> f64 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn abs(z: Complex) -> f64 {
    (z.real * z.real + z.imag * z.imag).sqrt()
}

impl Add<Complex> for Complex {
    type Output = Complex;

    fn add(self, other: Complex) -> Complex {
        Complex {
            real: self.real + other.real,
            imag: self.imag + other.imag,
        }  
    }  
}  
  
impl Sub<Complex> for Complex {
    type Output = Complex;
  
    fn sub(self, other: Complex) -> Complex {
        Complex {  
            real: self.real - other.real,
            imag: self.imag - other.imag,
        }  
    } 
}  
  
impl Mul<Complex> for Complex {
    type Output = Complex;  
  
    fn mul(self, other: Complex) -> Complex {  
        let real = self.real * other.real - self.imag * other.imag;
        let imag = self.real * other.imag + self.imag * other.real;
        Complex { real, imag }  
    }  
}

impl Div<Complex> for Complex {
    type Output = Complex;
  
    fn div(self, other: Complex) -> Complex {
        let real = (self.real * other.real + self.imag * other.imag) / (other.real * other.real + other.imag * other.imag);
        let imag = (self.imag * other.real - self.real * other.imag) / (other.real * other.real + other.imag * other.imag);
        Complex { real, imag }
    }
}  
  
impl Neg for Complex {
    type Output = Complex;
  
    fn neg(self) -> Complex {
        Complex {
            real: -self.real,
            imag: -self.imag,
        }
    }
}

fn main() {
    let z1 = Complex::new(2.0, 3.0);
    let z2 = Complex::new(3.0, 4.0);
    let z3 = Complex::new(3.0, -4.0);

    // 复数的四则运算
    let complex_add = z1.clone() + z2.clone();
    println!("{} + {} = {}", z1, z2, complex_add);

    let z = Complex::new(1.5, 0.5);
    println!("{} + {} = {}", z, z, z.clone() + z.clone());

    let complex_sub = z1.clone() - z2.clone();
    println!("{} - {} = {}", z1, z2, complex_sub);

    let complex_sub = z1.clone() - z1.clone();
    println!("{} - {} = {}", z1, z1, complex_sub);

    let complex_mul = z1.clone() * z2.clone();
    println!("{} * {} = {}", z1, z2, complex_mul);

    let complex_mul = z2.clone() * z3.clone();
    println!("{} * {} = {}", z2, z3, complex_mul);

    let complex_div = z2.clone() / z3.clone();
    println!("{} / {} = {}", z1, z2, complex_div);

    let complex_div = Complex::new(1.0,0.0) / z2.clone();
    println!("1 / {} = {}", z2, complex_div);

    // 对比两个复数是否相等
    println!("{:?}", z1 == z2);
    // 共轭复数
    println!("{:?}", z2 == z3.conj());
    // 复数的相反数
    println!("{:?}", z2 == -z3.clone() + Complex::new(6.0,0.0));

    // 复数的模
    println!("{}", z1.abs());
    println!("{}", z2.abs());
    println!("{}", abs(z3));
}

输出:

(2 + 3i) + (3 + 4i) = (5 + 7i)
(1.5 + 0.5i) + (1.5 + 0.5i) = (3 + i)
(2 + 3i) - (3 + 4i) = (-1 - i)
(2 + 3i) - (2 + 3i) = 0
(2 + 3i) * (3 + 4i) = (-6 + 17i)
(3 + 4i) * (3 - 4i) = 25
(2 + 3i) / (3 + 4i) = (-0.28 + 0.96i)
1 / (3 + 4i) = (0.12 - 0.16i)
false
true
true
3.605551275463989
5
5


小结

如此,复数的四则运算基本都实现了,当然复数还有三角表示式和指数表示式,根据它们的数学定义写出相当代码应该不是很难。有了复数三角式,就能方便地定义出复数的开方运算,有空可以写写这方面的代码。

本文完文章来源地址https://www.toymoban.com/news/detail-648762.html

到了这里,关于Rust 重载运算符|复数结构的“加减乘除”四则运算的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 插入运算符“>>“和提取运算符“<<“的重载

    🐶博主主页: @ᰔᩚ. 一怀明月ꦿ  ❤️‍🔥 专栏系列: 线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++ 🔥 座右铭: “不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 目录 🐰插

    2024年02月07日
    浏览(62)
  • 运算符重载和重载函数

    1.运算符重载的意义 C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。 函数名字为:operator后面接需要重载的运算符符号。 函数原型:返回值

    2024年02月06日
    浏览(41)
  • C++——类和对象3|日期类型|Cout运算符重载|Cin运算符重载|const成员|

    目录 日期类型  Date.h  Date.cpp  Test.cpp  实现Cout运算符重载  实现Cin运算符重载  根据日期算星期  修改后完整代码   Date.h  Date.cpp  const成员  取地址及const取地址操作符重载 习题  计算日期到天数转换     一个类到底可以重载哪些运算符,要看哪些运算符对这个类型有

    2023年04月13日
    浏览(58)
  • 【C++】运算符重载 ⑩ ( 下标 [] 运算符重载 | 函数原型 int& operator[](int i) | 完整代码示例 )

    在之前的博客 【C++】面向对象示例 - 数组类 ( 示例需求 | 创建封装类 | 数组类头文件 Array.h | 数组类实现 Array.cpp | 测试类 Test.cpp - 主函数入口 ) 中 , 实现了一个数组类 , 在一个类中 , 封装了一个 int 类型的指针 , 该指针指向堆内存的 内存空间 , 用于存放一个数组 ; 核心是 2

    2024年02月07日
    浏览(36)
  • C++修炼之筑基期第四层 ——透过日期类看运算符重载 | 赋值运算符重载 | 取地址操作符重载

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 本章主要

    2023年04月09日
    浏览(82)
  • 【C++】运算符重载

    目录 1. 基本概念 1.1 直接调用一个重载的运算符函数 1.2 某些运算符不应该被重载 1.3 使用与内置类型一致的含义 1.4 赋值和复合赋值运算符 1.5 选择作为成员或者非成员 2. 输入和输出运算符 2.1 输出运算符重载 2.2 输入运算符重载 3. 算术和关系运算符 3.1 算数运算符重载 3.2

    2024年02月11日
    浏览(48)
  • C++:重载运算符

    1.重载不能改变运算符运算的对象个数 2.重载不能改变运算符的优先级别 3.重载不能改变运算符的结合性 4.重载运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应该有一个是类对象,或类对象的引用 5.重载运算符的功能要类似于该运算符作用于标准类型数据

    2024年02月10日
    浏览(50)
  • C++——运算符重载

    运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。 运算符重载的目的是让语法更加简洁 运算符重载不能改变本来寓意,不能改变基础类型寓意 运算符重载的本质是另一种函数调用(是编译器去调用) 这个函数统一的名字叫opera

    2024年02月16日
    浏览(52)
  • 复习 --- C++运算符重载

    .5 运算符重载 运算符重载概念:对已有的运算符重新进行定义,赋予其另外一种功能,以适应不同的数据类型 4.5.1 加号运算符重载 作用:实现两个自定义数据类型相加的运算 4.5.2 左移运算符重载 4.5.3递增运算符重载 作用:通过重载递增运算符,实现自己的整型数据 4.5.4 赋

    2024年02月07日
    浏览(48)
  • kotlin 运算符重载解析

    反编译之后的java代码为: 可以看到实际是生成了一个 plus方法, 然后我们把我们的plus1方法名称修改为plus ,编译报错,提示有2个同名方法。 完美 。

    2024年02月15日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包