【转载】SAP程序属性中的固定点算术

发布时间 2024-01-10 17:48:34作者: 冰里取火
【转载地址】:https://www.cnblogs.com/zohoo/p/17337504.html
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为数不多的采用非固定点运算的方式所开发的标准程序之一,如下图所示:

  因此当我们增强销售订单相关单据后,出现的运算的结果缩小了一定的倍数,皆是因为这个原因所导致。