Rust 复数运算,重载加减乘除运算

news2024/11/26 20:36:28

eb88291a18a94ba4ace118fb4e46ef23.png

复数

基本概念

复数定义

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

其中a、b为实数,i 为“虚数单位”,i 的平方等于-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)

乘法法则

复数的乘法法则:把两个复数相乘,类似两个多项式相乘,结果中i2=-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的商。

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

复数的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/877724.html

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

相关文章

安世收购英国最大晶圆制造厂

据英国《泰晤士报》报道&#xff0c;英国Newport晶圆厂的员工 给 《 泰晤士报 》 的一封措辞强硬的信中&#xff0c;表 示 代表582名员工的员工协会表示。Newport晶圆厂员工们完全支持Nexperi a安世半导体 对工厂的所有权。因为Nexperia提供 了稳定的工作、改善了工作保障、工资…

VBA 学习笔记1 对象以及属性

目录 1 取得VBA对象1.1 取得工作簿对象1.2 取得工作表对象1.3 取得单元格对象1.4 取得对象的属性1.5 文档的方法1 进入vba 界面 方式之一&#xff1a; 快捷键&#xff1a;ALTERF11 运行方式之一&#xff1a; 进入vba界面&#xff0c;点击绿色三角符号 1 取得VBA对象 1.1 取得…

Win10基于 Anaconda 配置 Deeplabcut 环境

最近需要做动物行为学分析的相关研究&#xff0c;同时由于合作者只有 Windows 系统&#xff0c;于是只好在 Windows 中配置环境。说实话还真的是挺折磨的。。。 一、下载 Anaconda 可以通过清华源下载 Anaconda&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/ar…

leetcode剑指 Offer 58 - II. 左旋转字符串(两种方法)

题目&#xff1a;leetcode剑指 Offer 58 - II. 左旋转字符串 描述&#xff1a; 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如&#xff0c;输入字符串"abcdefg"和数字2&#xff0c;该函数将返回…

Gradle依赖管理:编译时和运行时依赖的区别

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

nsq中diskqueue详解 - 第一篇

一、diskqueue是什么&#xff0c;为什么需要它 在nsq中消息主要存在于两种队列 一种是内存队列&#xff0c;内部是用go的通道实现&#xff0c;所以处理速度很快&#xff0c;缺点是一旦nsqd进程挂掉消息就丢失了&#xff0c;这让人难以接受&#xff0c;数据丢了不得被用户骂死…

强训第31天

选择 传输层叫段 网络层叫包 链路层叫帧 A 2^16-2 C D C 70都没收到&#xff0c;确认号代表你该从这个号开始发给我了&#xff0c;所以发70而不是71 B D C 248&123120 OSI 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 C 记一下304读取浏览器缓存 502错误网关 编…

论文总结《Adversarial Personalized Ranking for Recommendation(APR)》

原文链接 APR、 本篇论文是对抗训练在RS领域的先锋作&#xff0c;在这篇文章前对抗训练应用在图像领域&#xff0c;以提高模型鲁棒性。本篇论文填补了对抗训练在RS领域的空缺&#xff0c;首次基于BPR进行对抗训练&#xff0c;以提高RS排序模型的鲁棒性。 Motivation 文章在…

Python脚本之连接MySQL【四】

本文为博主原创&#xff0c;未经授权&#xff0c;严禁转载及使用。 本文链接&#xff1a;https://blog.csdn.net/zyooooxie/article/details/124640412 之前写了篇 Python脚本之连接MySQL【三】&#xff0c;日常使用过程中&#xff0c;代码实际有很多改动&#xff0c;特此更新…

数据分析--帆软报表--大数据大屏

进入国企公司学习有一段时间了&#xff0c;岗位是数据分析方向------ 母前使用的是帆软工具进行的开发。 可以进行大数据大屏 也可使嵌入到手机端。 下面是例子

IntelliJ IDEA快捷键大全 + 动图演示

IntelliJ IDEA快捷键大全 动图演示 &#x1f60d; 一、构建/编译Ctrl F9&#xff1a;构建项目Ctrl Shift F9&#xff1a;重新编译当前类 &#x1f60d; 二、文本编辑Ctrl X&#xff1a;剪切Ctrl C&#xff1a;复制Ctrl V&#xff1a;粘贴Ctrl Alt Shift V&#xff1a…

Nginx安装及Minio集群反向动态代理配置(二)

安装所需插件 1、安装gcc gcc是linux下的编译器在此不多做解释&#xff0c;感兴趣的小伙伴可以去查一下相关资料&#xff0c;它可以编译 C,C,Ada,Object C和Java等语言 命令&#xff1a;查看gcc版本 [rootwww ~]# gcc -v -bash: gcc: 未找到命令 说明没有安装: 那就直接yu…

mclust学习总结

mclust example1 import numpy as np import pandas as pd from matplotlib import pyplot as plt from sklearn.datasets import make_blobs X, y make_blobs(n_samples300, centers4, cluster_std0.60, random_state0) # n_features2是默认的 plt.scatter(X[:,0], X[:,1]) …

Java【数据结构】二分查找

&#x1f31e; 题目&#xff1a; &#x1f30f;在有序数组A中&#xff0c;查找目标值target &#x1f30f;如果找到返回索引 &#x1f30f;如果找不到返回-1 算法描述解释前提给定一个内含n个元素的有序数组A&#xff0c;满足A0<A1<A2<<An-1,一个待查值target1设…

如何利用 EMC 模型解决能源服务提供商的瓶颈

01. 什么是合同能源管理&#xff1f; 合同能源管理(EMC-Energy Management Contract) 是一种新型的市场化节能机制,其实质就是以减少的能源费用来支付节能项目全部成本的节能投资方式。&#xff1a;节能服务公司与用能单位以契约形式约定节能项目的节能目标&#xff0c;节能服…

在 ubuntu 18.04 上使用源码升级 OpenSSH_7.6p1到 OpenSSH_9.3p1

1、检查系统已安装的当前 SSH 版本 使用命令 ssh -V 查看当前 ssh 版本&#xff0c;输出如下&#xff1a; OpenSSH_7.6p1 Ubuntu-4ubuntu0.7, OpenSSL 1.0.2n 7 Dec 20172、安装依赖&#xff0c;依次执行以下命令 sudo apt update sudo apt install build-essential zlib1g…

springBoot 简单的demo

springBoot 学习开始 场景开发流程1、创建项目2、导入依赖3、创建启动springBoot 项目的主入口程序4、创建业务程序5、在MainApplication文件运行程序6、将文件打包成jar包 遇到的问题未解决 希望大哥们帮忙--本地运行jar包报错 场景 浏览器发送hello请求&#xff0c;返回“he…

培训报名小程序-用户注册

目录 1 创建数据源2 注册用户3 判断用户是否注册4 完整代码总结 我们的培训报名小程序&#xff0c;用户每次打开时都需要填写个人信息才可以报名&#xff0c;如果用户多次报名课程&#xff0c;每次都需要填写个人信息&#xff0c;比较麻烦。 本篇我们就优化一下功能&#xff0c…

[静态时序分析简明教程(十)]模式分析与约束管理

静态时序分析简明教程-组合电路路径 一、写在前面1.1 快速导航链接 二、模式分析三、约束管理3.1 自顶向下的方法3.2 自底向上的方法 四、总结 一、写在前面 一个数字芯片工程师的核心竞争力是什么&#xff1f;不同的工程师可能给出不同的答复&#xff0c;有些人可能提到硬件描…

新品牌怎么进行产品营销,小红书布局指南!

随着互联网的快速发展&#xff0c;新品牌们逐渐意识到小红书这一平台的潜力。平台庞大的用户群体和高度活跃的内容创作者&#xff0c;成为新品牌布局的理想之地。今天&#xff0c;就来和大家分享一下新品牌怎么进行产品营销&#xff0c;小红书布局指南&#xff01; 第一步&…