D语言中的浮点运算

博客围绕浮点运算展开,提及浮点运算中间值可能使用高于表达式类型要求的精度,优化代码或使结果更精确,float 或 double 类型可减少内存消耗、维持与 C 的兼容性。还探讨了负数和虚数类型,添加新类型可让复数语义正常,虚数类型能提升运算性能。
 

浮点

浮点运算中间值

在许多计算机上,使用较高精度的运算并不比使用较低精度的运算耗费的时间长,所以为内部的临时变量采用机器允许的最高精度对于数值运算是有意义的。这里采用的哲学是不强求语言为统一而采用各种硬件的最低精度,从而充分利用目标硬件的最佳性能。

对于浮点运算表达式的中间值来说,可能会使用高于表达式类型所要求的精度。操作数的类型只决定最低精度而不是最高精度。实现注记:例如,在 Intel x86 机器上,计算的中间步骤最好(但不是必需)使用硬件提供的全部 80 位精度。

如果临时变量和公共子表达式的使用量很大的话,优化后的代码很可能会得到比未优化代码更精确的解。

算法应该以计算的最小精度为基础。如果实际的精度更高,它们也不应该退化或者失败。同扩展类型不同,float 或者 double 类型应该用于:

  • 减少大型数组的内存消耗
  • 维持同 C 的数据和函数参数的兼容性

负数和虚数类型

在现有的语言中,为了将复数类型添加到现存类型体系中可谓费尽周折:模板、结构、运算符重载等等,并且最终的结果几乎都是失败。失败的原因可能是由于复数运算的语义很微妙,是由于编译器不理解程序员想要做什么,因而无法对语义的实现进行优化。

所有这些的目的都只是为了避免加入一个新类型。添加一个新类型意味着编译器可以使所有的复数语义工作“正常”。然后程序员就可以依靠复数的正确(至少是稳定)的实现。

伴随而来的是对虚数的需求。虚数类型是我们可以避开一些微妙的语义问题,并且由于不用处理隐含的 0 实部,可以提高运算的性能。

虚数文字量有一个 i 作为后缀:

	ireal j = 1.3i;
	
复数文字量没有自身特殊的语法,只需写成实数类型和虚数类型相加即可:
	cdouble cd = 3.6 + 4i;
	creal c = 4.5 + 2i;
	
复数有两个属性:
	.re	实数部分
	.im	虚数部分
	
例如:
	cd.re		是 4.5 double
	cd.im		是 2 double
	c.re		是 4.5 real
	c.im		是 2 real
	

取整控制

IEEE 754 浮点数算术包括了设置四种不同的取整模式的能力。D 加入了支持它们的语法:[blah, blah, blah] [注记:也许使用标准库更好]

异常标志

IEEE 754 浮点数算术可以为计算中发生的事件设立标志:[blah, blah, blah] 这些标志可以使用如下如法设置/重置:[blah, blah, blah] [注记:也许使用标准库更好]

浮点比较

除了常用的 <、<=、>、>=、== 和 != 比较运算符外,D 另外提供了专用于浮点数的运算符。它们是 !<>=、<>、<>=、!<=、!<、!>=、!> 和 !<>,并符合 C 扩展 NCEG 的语义。
	浮点数比较运算符	运算符关系	无效? 	描述

			> < = ? 

	<		F T F F		yes 	小于
	>		T F F F		yes 	大于
	<=		F T T F		yes	小于或等于
	>=		T F T F		yes	大于或等于
	==		F F T F		no	等于
	!=		T T F T		no	未定义、小于或大于
	!<>=		F F F T		no	未定义
	<>		T T F F		yes	小于或大于
	<>=		T T T F		yes	小于、等于或大于
	!<=		T F F T		no	未定义或大于
	!<		T F T T		no	未定义、大于或等于
	!>=		F T F T		no	未定义或小于
	!>		F T T T		no	未定义、小于或等于
	!<>		F F T T		no	未定义或等于
	
<think>我们正在讨论三菱PLC的ST语言编程,特别是浮点数运算的实现。根据用户的问题,用户希望了解如何在三菱PLC中使用结构化文本(ST)进行浮点数运算。 首先,我们需要明确三菱PLC的编程环境。三菱PLC的编程软件GX Works2和GX Works3支持结构化文本(ST)语言。ST语言是一种高级文本语言,类似于Pascal或C,支持复杂的数学运算,包括浮点数运算。 在三菱PLC中,浮点数通常以实数(REAL)类型表示。REAL类型占用32位,符合IEEE 754标准。在ST语言中,我们可以直接使用实数变量进行运算。 步骤: 1. 声明变量:在ST程序中,首先需要声明使用的变量,包括实数变量。 2. 进行运算:使用ST语言的算术运算符进行浮点数运算。 3. 处理结果:将运算结果赋值给其他变量或用于控制。 示例: 假设我们有两个实数变量a和b,我们想要计算它们的和、差、积、商。 ```st PROGRAM Main VAR a : REAL := 10.5; b : REAL := 3.2; sum : REAL; difference : REAL; product : REAL; quotient : REAL; END_VAR BEGIN sum := a + b; difference := a - b; product := a * b; quotient := a / b; END_PROGRAM ``` 注意事项: 1. 除法运算中,注意除数不能为零,否则会导致运行时错误。在实际编程中,应加入条件判断。 2. 浮点数运算可能存在精度问题,这是由浮点数的表示方式决定的,在比较浮点数时,应避免直接使用等号比较,而应检查两数之差是否在一个很小的范围内。 另外,三菱PLC还提供了一些数学函数,如三角函数、指数函数、对数函数等,这些函数可以在ST语言中直接调用。例如: ```st VAR x : REAL := 0.5; sin_val : REAL; cos_val : REAL; exp_val : REAL; log_val : REAL; END_VAR BEGIN sin_val := SIN(x); // 正弦函数 cos_val := COS(x); // 余弦函数 exp_val := EXP(x); // 指数函数e^x log_val := LN(x); // 自然对数 END ``` 在编程时,需要确保使用的函数在PLC的指令集中支持。三菱FX系列PLC(如FX3U)支持基本的浮点数运算指令,但一些高级函数可能需要特定的模块或更高系列的PLC(如Q系列)才能支持。 此外,用户还应注意PLC的扫描周期对运算的影响。浮点数运算通常比整数运算耗时更长,在实时性要求高的场合,应合理规划程序结构,避免在高速扫描的任务中进行复杂的浮点运算。 总结: 在三菱PLC中使用ST语言进行浮点数运算,主要步骤包括: - 声明实数变量 - 使用算术运算符(+、-、*、/)进行基本运算 - 调用数学函数(如SIN、COS等)进行复杂运算 - 注意运算中的异常情况(如除数为零)和精度问题 通过以上步骤,用户可以在三菱PLC中实现浮点数运算。 §§相关问题§§ 1. 在三菱PLC中,如何避免浮点数运算中的除零错误? 2. 三菱PLC的ST语言支持哪些数学函数? 3. 如何提高浮点数运算在三菱PLC中的执行效率? 4. 三菱FX系列PLC和Q系列PLC在浮点数运算支持上有何区别?</think>### 在三菱PLC中使用ST语言实现浮点数运算 在三菱PLC(如FX3U/FX5U系列)中,使用结构化文本(ST语言)进行浮点数运算需要掌握以下关键步骤: #### 1. **声明浮点数变量** ```st VAR fValue1 : REAL; (* 单精度浮点数 *) fValue2 : LREAL; (* 双精度浮点数,FX5U系列支持 *) fResult : REAL; END_VAR ``` - `REAL`类型符合IEEE 754标准(32位) - `LREAL`类型提供更高精度(64位),需确认PLC型号支持[^3] #### 2. **基本算术运算** ```st fResult := fValue1 + fValue2; (* 加法 *) fResult := fValue1 - fValue2; (* 减法 *) fResult := fValue1 * fValue2; (* 乘法 *) fResult := fValue1 / fValue2; (* 除法 *) ``` #### 3. **高级函数运算** ```st fResult := SIN(fValue1); (* 正弦函数 *) fResult := COS(fValue1); (* 余弦函数 *) fResult := SQRT(fValue1); (* 平方根 *) fResult := EXP(fValue1); (* 指数函数 *) fResult := LOG(fValue1); (* 自然对数 *) ``` #### 4. **比较运算** ```st IF fValue1 > fValue2 THEN (* 执行操作 *) ELSIF ABS(fValue1 - fValue2) < 0.001 THEN (* 浮点数等值判断 *) (* 处理近似相等 *) END_IF; ``` #### 5. **类型转换** ```st iInteger := REAL_TO_INT(fValue1); (* 浮点转整数 *) fValue1 := INT_TO_REAL(iInteger); (* 整数转浮点 *) ``` #### 6. **注意事项** - **除零保护**:必须添加防除零判断 ```st IF fValue2 <> 0.0 THEN fResult := fValue1 / fValue2; ELSE (* 错误处理 *) END_IF; ``` - **精度问题**:避免直接比较浮点数相等,使用容差范围 - **扫描周期**:复杂运算可能延长PLC扫描时间,需优化逻辑 - **特殊寄存器**:通过`D`寄存器存储浮点数(如`D0`存储32位浮点值)[^1] #### 示例代码:温度PID计算 ```st VAR fSetTemp : REAL := 50.0; fActualTemp : REAL; fError, fIntegral, fDerivative : REAL; fKp, fKi, fKd : REAL := 0.8, 0.05, 0.1; fOutput : REAL; END_VAR fError := fSetTemp - fActualTemp; fIntegral := fIntegral + fError; fDerivative := fError - fPrevError; fOutput := (fKp * fError) + (fKi * fIntegral) + (fKd * fDerivative); fPrevError := fError; ``` > **关键优势**:ST语言相比梯形图更易实现复杂数学运算,代码可读性更高[^4]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值