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

news2024/10/5 13:41:56

eb88291a18a94ba4ace118fb4e46ef23.png

复数

基本概念

复数定义

由实数部分和虚数部分所组成的数,形如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


小结

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

本文完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/879162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

codeforces代:

感受思维的美丽&#xff0c;abcde题目的思路是怎么样的&#xff1a; 上蓝 上紫 可以代 &#xff1a;有问题可以评论区 直接问我 也可以q: 639682754

【严重】Smartbi未授权设置Token回调地址获取管理员权限

漏洞描述 Smartbi是一款商业智能应用&#xff0c;提供了数据集成、分析、可视化等功能&#xff0c;帮助用户理解和使用他们的数据进行决策。 在 Smartbi 受影响版本中存在Token回调地址漏洞&#xff0c;未授权的攻击者可以通过向目标系统发送POST请求/smartbix/api/monitor/s…

python_PyQt5运行股票研究python方法工具V1.0

写在前面&#xff1a; 1 在写研究方法过程中&#xff08;例如&#xff1a;股票研究&#xff09;&#xff0c;很多方法根据数据的更新需要重复运行获取新的结果&#xff0c;本工具就是固化这些需要重复运行的代码&#xff0c;可以直接在工具中运行得到更新的结果。 2 本文是V1…

并发编程系列-Semaphore

Semaphore&#xff0c;如今通常被翻译为"信号量"&#xff0c;过去也曾被翻译为"信号灯"&#xff0c;因为类似于现实生活中的红绿灯&#xff0c;车辆是否能通行取决于是否是绿灯。同样&#xff0c;在编程世界中&#xff0c;线程是否能执行取决于信号量是否允…

DevOps?自动化运维!

by: 雪月三十 DevOps流程图 DevOps介绍 命名 DevOps是Dev和Ops的结合 Dev&#xff08;developer开发&#xff09; Ops&#xff08;operation运维&#xff09; 矛盾 在企业中dev和ops是有一种天然的矛盾&#xff0c;dev要求的是快速迭代&#xff0c;给公司挖掘出商业的价值…

c++实现多进程执行多个shell脚本

一 参考 system()、exec()、fork()三个与进程有关的函数的比较 - 青儿哥哥 - 博客园 (cnblogs.com)https://www.cnblogs.com/qingergege/p/6601807.htmlfork执行流程分析_fork子进程和父进程执行顺序_cytf的博客-CSDN博客https://blog.csdn.net/qq_27420299/articl

IE实验-Qos教学实验

S1 diffserv domain boss //创建差分服务域 8021p-inbound 0 phb ef green //将外部优先级为0的流量&#xff0c;映射到内部优先级ef interface GigabitEthernet0/0/2 trust upstream boss //在接口下调用查分服务域 trust dscp override qos map-table dscp-dscp acl …

【新品发布】ChatWork企业知识库系统源码

系统简介 基于前后端分离架构以及Vue3、uni-app、ThinkPHP6.x、PostgreSQL、pgvector技术栈开发&#xff0c;包含PC端、H5端。 ChatWork支持问答式和文档式知识库&#xff0c;能够导入txt、doc、docx、pdf、md等多种格式文档。 导入数据完成向量化训练后&#xff0c;用户提问…

小米发布会:雷军成长故事与创新壮举,AI大模型技术引领未来,雷军探索之路之从创业波折到小米AI领航,成就高端化传奇!

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于物理场的动态模式分解(piDMD)研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

翻转二叉树

声明 该系列文章仅仅展示个人的解题思路和分析过程&#xff0c;并非一定是优质题解&#xff0c;重要的是通过分析和解决问题能让我们逐渐熟练和成长&#xff0c;从新手到大佬离不开一个磨练的过程&#xff0c;加油&#xff01; 原题链接 翻转二叉树备战技术面试&#xff1f;…

shell之正则表达式及三剑客grep命令

一、正则表达式概述 什么是正则表达式&#xff1f; 正则表达式是一种描述字符串匹配规则的重要工具 1、正则表达式定义: 正则表达式&#xff0c;又称正规表达式、常规表达式 使用字符串描述、匹配一系列符合某个规则的字符串 正则表达式 普通字符&#xff1a; 大小写字母…

LED全彩显示屏的前后维护

LED全彩显示屏的维护问题成为一个备受关注的难题。特别是对于采用镶嵌式或壁挂式安装的用户而言&#xff0c;检修和维护工作变得异常繁琐&#xff0c;仿佛一举一动都会影响整体运行。在这一背景下&#xff0c;LED全彩显示屏不仅需要符合严格的标准化要求&#xff0c;更需要具备…

【CHI】(三)网络层

网络层负责确定目标节点的NodeID。本章包含以下部分&#xff1a; 系统地址映射&#xff0c;SAM节点ID目标ID确定网络层flow示例 1. System address map 系统中每个Requester(包括RN和HN)必须有一个System Address Map(SAM)来决定一个request的target ID。SAM的范围可能只是简…

【Spring】深入探索 Spring AOP:概念、使用与实现原理解析

文章目录 前言一、初识 Spring AOP1.1 什么是 AOP1.2 什么是 Spring AOP 二、AOP 的核心概念2.1 切面&#xff08;Aspect&#xff09;2.2 切点&#xff08;Pointcut&#xff09;2.3 通知&#xff08;Advice&#xff09;2.4 连接点&#xff08;Join Point&#xff09; 三、Sprin…

Android复习(Android基础-四大组件)——Broadcast

1. 广播分类 广播的发送方式&#xff1a;标准广播、有序广播、粘性广播广播的类型&#xff1a;系统广播、本地广播 1.1 标准广播 完全异步&#xff0c;无序的广播发出后&#xff0c;所有的广播接收器几乎都会在同一时间收到消息。&#xff08;异步&#xff09;但是消息无法截…

科技云报道:算力之战,英伟达再度释放AI“炸弹”

科技云报道原创。 近日&#xff0c;在计算机图形学顶会SIGGRAPH 2023现场&#xff0c;英伟达再度释放深夜“炸弹”&#xff0c;大模型专用芯片迎来升级版本。 英伟达在会上发布了新一代GH200 Grace Hopper平台&#xff0c;该平台依托于搭载全球首款搭载HBM3e处理器的新型Grac…

Java并发之ReentrantLock

AQS AQS&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff1a;抽象队列同步器&#xff0c;是一种用来构建锁和同步器的框架。在是JUC下一个重要的并发类&#xff0c;例如&#xff1a;ReentrantLock、Semaphore、CountDownLatch、LimitLatch等并发都是由AQS衍生出来…

ElementUI的MessageBox的按钮置灰且不可点击

// this.$confirmthis.$alert(这是一段内容, 标题名称, {confirmButtonText: 确定,confirmButtonCLass: confirmButton,beforeClose: (action,instance,done) > {if (action confirm) {return false} else {done()}});}.confirmButton {background: #ccc !important;cursor…

淘宝API接口的实时数据和缓存数据区别

电商API接口实时数据是指通过API接口获取到的与电商相关的实时数据。这些数据可以包括商品库存、订单状态、销售额、用户活跃度等信息。 通过电商API接口&#xff0c;可以实时获取到电商平台上的各种数据&#xff0c;这些数据可以帮助企业或开发者做出及时的决策和分析。例如&…