【转载】SAP程序属性中的固定点算术
SAP程序创建时,程序属性面板中有一个选项叫做“固定点算术”,默认是勾上的,如下图所示:
通过按F1在该选上调取帮助说明,可以看到官方是这样解释的:
- 如果标记该复选框,该程序中的所有计算都将使用定点运算。
- 如果未标记,那么当在分配、比较和计算中使用压缩数字,与定义的小数位无关时,就把压缩数字(ABAP/4 类型 P、字典类型 CURR、DEC 或 QUAN )作为正数。也将把算法计算中的中间结果取整到下一整数。只有当使用 WRITE 报表输出该答复时,才考虑该小数位数量。
这段机翻的说明读起来是相当费解的,简单来说就是这样的:
如果勾选固定算术,则在程序中所有的运算都是基于真实值进行运行,无需特殊处理;
如果不勾选固定算术,则在程序中,压缩类型的数值类型(比如P、CURR、QUAN)都变量都会先视为不带小数点的正整数,来进行运算、比较或者分配,处理完毕后,使用write类型输出的时候,系统会对运算结果再补上数据类型对应的小数点,超出小数点位数的,按照四舍五入的原则舍弃多余的小数位。
详见下方测试代码(程序属性设置为非固定点算术):
DATA: LV_PACK_NUM1 TYPE P DECIMALS 3, "压缩数据1 LV_PACK_NUM2 TYPE P DECIMALS 3, "压缩数据2 LV_FACTOR1 TYPE I, "除数1 LV_FACTOR2 TYPE I. "除数2 LV_PACK_NUM1 = '12345.6'. LV_PACK_NUM2 = '12345.6'. LV_FACTOR1 = 100. LV_FACTOR2 = 1000. LV_PACK_NUM1 = LV_PACK_NUM1 / LV_FACTOR1. LV_PACK_NUM2 = LV_PACK_NUM2 / LV_FACTOR2. WRITE:/ LV_PACK_NUM1,/ LV_PACK_NUM2.
运行结果如下:
我们分析下运算过程:
对于LV_PACK_NUM1='12345.6',计算之前,先将数据的小数点移除,变成了 LV_PACK_NUM1='123456',除以100后,变成了1234.56,然后由于LV_PACK_NUM1定义的是三位小数,因此再在结果上补充三位小数,变成了 1.23456,然后根据小数点第四位(为5)进行四舍五入,于是小数点第三位就从4变成了5,要进位,所以最终结果 1.235;而该算式正常运算的话,结果应该是123.456
对于LV_PACK_NUM2='12345.6',计算之前,先将数据的小数点移除,变成了 LV_PACK_NUM2='123456',除以1000后,变成了123.456,然后由于LV_PACK_NUM2定义的是三位小数,因此再在结果上补充三位小数,变成了 0.123456,然后根据小数点第四位(为4)进行四舍五入,于是小数点第三位的3还是3,所以最终结果 0.123;而该算式正常运算的话,结果应该是12.346,
如下对比表
运算式
|
固定点运算
|
非固定点运算
|
||
常规运算
|
移除小数点->
|
补充小数点->
|
四舍五入
|
|
12345.6÷100
|
123.456
|
123456÷100=1234.56
|
1.23456
|
1.235
|
12345.6÷1000
|
12.3456
|
123456÷1000=123.456
|
0.123456
|
0.123
|
由此可见,一旦 程序采用非固定运算的方式开发,往往会导致计算结果的异常,要解决此问题,需要将运算过程封装成一个采用固定点运算的Funcion来运算,运算完后,传出结果到调用程序中。
常见应用于SD模块中得的一代出口增强中,由于SAP预留的一代出口均包含在模块池程序SAPMV45A中,而这个程序正好是SAP为数不多的采用非固定点运算的方式所开发的标准程序之一,如下图所示:
因此当我们增强销售订单相关单据后,出现的运算的结果缩小了一定的倍数,皆是因为这个原因所导致。