算术表达式

算术表达式 (★★)

#arithmetic #data-types

数值类型比较

类型 关键字 精度 范围 特殊行为
整数 i 4 字节,整数 -2^31 到 2^31-1 商业舍入用于除法
二进制浮点 f 8 字节,IEEE 754 ~1E-307 到 ~1E+308 舍入误差;17位显示
压缩数 p 1-16 字节,1-31 位 最多 31 位 需要 DECIMALS;需要定点算术属性
十进制浮点 16 decfloat16 8 字节 16位精度 笔纸算法;无舍入误差
十进制浮点 34 decfloat34 16 字节 34位精度 笔纸算法;无舍入误差

整数算术

  • 商业舍入:除法舍入到最接近的整数(不是截断)
  • DIV 运算符:整数除法返回商
  • MOD 运算符:整数取模返回余数
1
2
3
4
5
6
7
8
DATA: lv_int TYPE i.

lv_int = 5 / 2. " 结果:3(商业舍入)
lv_int = -5 / 2. " 结果:-2(向绝对值更大的方向舍入)

" DIV 和 MOD
lv_result = 7 DIV 2. " = 3
lv_result = 7 MOD 2. " = 1
📌整数除法使用商业舍入,不是截断。5 / 2 = 3,而不是 2

二进制浮点数(类型 f)

  • 基于 IEEE 754 标准(双精度)
  • 内部以二进制尾数 + 指数存储
  • 无法精确表示所有十进制小数
  • 显示使用 17 位有效数字(足以重建二进制值)
  • 比较可能因舍入而失败:0.1 + 0.2 <> 0.3 可能为真
1
2
3
4
DATA: lv_float TYPE f.

lv_float = '0.1'. " 必须使用文本字面量进行精确的十进制输入
lv_float = 0.1. " 转换时可能已有舍入误差
⚠️类型 f 有舍入误差。绝不要用于财务计算。应使用 pdecfloat

压缩数(类型 p)

  • 定点算术:小数点随值一起存储
  • 使用 LENGTH(字节)和 DECIMALS(小数位)定义
  • 总位数 = 2 * LENGTH - 1
  • **程序属性”定点算术”**必须激活
    • 如果未设置:计算中忽略小数位;仅用于 I/O 格式化
1
2
3
4
5
DATA: lv_packed TYPE p LENGTH 8 DECIMALS 2.

" 不带定点算术属性:
" 1.50 + 1.50 = 3.00 (存储/打印正确)
" 1.50 * 2 = 300 (错误!计算中未考虑小数位)
📌如果程序属性”定点算术”未设置,类型 p 的计算忽略小数位。结果仅在输出时显示正确,但内部算术将值当作整数处理。

十进制浮点数(decfloat16 / decfloat34)

  • 使用笔纸算法(基于十进制,非二进制)
  • 十进制小数无舍入误差
  • decfloat16:16 位有效数字,8 字节
  • decfloat34:34 位有效数字,16 字节
  • 财务和精度关键计算的最佳选择

混合算术类型确定

当不同数值类型出现在同一表达式中时,结果类型遵循优先级层次

1
2
3
4
5
优先级(从高到低):
decfloat16 / decfloat34 --> 十进制浮点算术
f --> 二进制浮点算术
p --> 压缩(定点)算术
i --> 整数算术
条件 使用的算术
任何 decfloat16/decfloat34 操作数或结果 十进制浮点
任何 f 操作数或结果(无 decfloat) 二进制浮点
任何 p 操作数或结果(无 f,无 decfloat) 定点(压缩)
所有 i 操作数和结果 整数
⚠️**(幂)运算符始终触发二进制或十进制浮点算术,即使所有操作数都是 i 类型。
1
2
3
4
5
" 示例:** 改变一切
DATA: lv_int TYPE i.

lv_int = ( 1 / 4 ) * ( 2 * 2 ). " 整数算术:(0) * 4 = 0
lv_int = ( 1 / 4 ) * ( 2 ** 2 ). " 浮点算术:0.25 * 4.0 = 1
⚠️超出 i 范围(|value| > 2,147,483,647)的数字字面量自动变为 p 类型。这会静默更改整个表达式的算术类型。
1
2
3
4
5
" 大字面量将算术改为压缩数
DATA: lv_int TYPE i.

lv_int = 1000000000 / 300000000 * 3. " 整数:结果 = 9
lv_int = 10000000000 / 3000000000 * 3. " 压缩数:结果 = 10

算术运算符汇总

运算符 含义 说明
+ - 加、减 标准
* / 乘、除 类型相关
DIV 整数商 仅整数类型
MOD 整数余数 仅整数类型
** 始终触发浮点算术
**= 幂并赋值 内联版本

选择正确的数值类型

1
2
3
4
5
6
7
8
9
10
+------------------+------------------------------------------+
| 使用场景 | 推荐类型 |
+------------------+------------------------------------------+
| 计数、索引 | i (最快,原生) |
| 财务计算 | p 或 decfloat34 (精确小数) |
| 科学计算 | f (大范围,IEEE 754) |
| 最高精度 | decfloat34 (34位,无舍入) |
| 高精度 | decfloat16 (16位,更少内存) |
| 遗留代码 | p (传统 ABAP) |
+------------------+------------------------------------------+

考试/测试模式

关键词/模式 答案
“商业舍入” 整数除法舍入到最接近的整数
“类型 f 舍入误差” IEEE 754 二进制无法精确表示所有十进制小数
“17 位” 类型 f 的显示精度
“定点算术” 程序属性;必须为类型 p 的小数位设置
“笔纸算法” decfloat 算法;无舍入误差
** 运算符” 无论操作数类型如何,都强制浮点算术
“字面量超出 i 范围” 自动变为 p 类型;改变表达式算术
“decfloat vs f” decfloat = 精确十进制;f = 带舍入误差的二进制
“DIV / MOD” 整数商和余数运算符
“混合表达式类型” 由表达式中最高优先级的类型决定

相关笔记