1. 引言

通常,有两种对编程语言的改进。第一种是让困难的事情变得简单,第二种是让不可能的事情变为可能。本文介绍的是任意精度算术,它属于第二类:使在ABAP中原本不可能的事情成为可能。

过去已经可以在ABAP中使用INT8或DECFLOAT34数据类型进行非常大的数字计算,但还不能进行任意精度的计算。使用这两种数据类型,也有溢出的风险。

尽管DECFLOAT34可以对非常大的数字进行操作,但其精度仅为34位。这意味着当你进行更复杂的计算时,可能会得到错误的结果。典型的问题是当加减不同大小类别的数字时,例如:

larger_number + smaller_number - larger_number = 0

原因是大数没有足够的精度来反映小数的加法。如果你再减去大数,会得到零。小并不意味着数字真的很小,只是它比较大的数字小得多。所以在这种情况下,10000可能是小的。

许多编程语言提供了任意精度算术的能力。例如,Java有BigInteger和BigDecimal类,Python的整数数据类型默认为任意精度,而C#也提供了一个BigInteger数据类型。C++语言有著名的GMP和MPFR库用于任意精度算术。

英文原文:New classes for arbitrary precision arithmetic in ABAP

本文链接:https://www.cnblogs.com/hhelibeb/p/17868032.html

2. 不同种类的任意精度算术

通常,编程语言中有三种任意精度算术库。第一种是任意精度整数算术。这允许用任意大的整数进行计算。可以假想这种类型的数字为INT∞。当然,数字并非真的可以任意长,但受限于系统的主内存的容量。然而,对于每个实际应用,你可以假想结果的数字为无穷大。

这种库的典型质量标准是乘法指令的速度和时间复杂度。经典的教科书乘法复杂度为log(N)²,因为你需要将第一个数的每一位与第二个数的每一位相乘。令人惊奇的是,有更有效的乘法算法,最简单的就是众所周知的Karatsuba算法。

一般来说,任意精度整数算术的库也提供了一些数论操作的可能性,例如,确定质数和计算GCD(最大公约数)。

下一种类型的任意精度数字是任意精度有理数。任意精度有理数是两个任意精度整数的商a / b。注意,每个具有有限小数的十进制数都是一个有理数,例如,1.01 = 101 / 100。因此,每个固定大小的ABAP类型P/DEC的十进制数都可以写成一个有理数。由于精度仍然是有限的,同样的,每个DECFLOAT34类型的数字也可以写成一个有理数。

有理数在这个意义上是复杂的,即分数必须被简化,例如,2 / 4 = 1 / 2。因此,实现有理数要求有一个好的GCD算法。

有理数算术库不提供像EXP或LOG这样的超越函数,甚至其他简单的操作,如平方根。这是因为有理数的指数和对数只在非常特定的情况下也是有理数。平方根也是如此。

对于平方根,有一个简单的技巧可以计算任意数量的数字,只需使用整数算术。然而,对于超越函数,没有类似的技巧。

为了计算超越函数,你需要一个任意精度浮点(或实数)算术库。这些库可以计算具有任意给定精度的实数。例如,你可以决定用100,1000,或10000位来计算2的对数。

3. 在ABAP中的任意精度算术

在过去,ABAP没有任何形式的任意精度算术的能力。随着2308版本和793内核的发布,ABAP引入了两个新的类:CL_ABAP_BIGINTCL_ABAP_RATIONAL,用于实现任意精度的整数和有理数算术。另外,虽然CL_ABAP_RATIONAL在内部实现中使用了任意精度的实数算术来进行其转换到DECFLOAT34,但ABAP尚未公开任意精度的实数算术功能。

这两个类都是侵入式的,这意味着如果你向一个数添加另一个数,你不会得到一个新的实例,而是原来的实例会被改变。考虑以下编码:

result_bigint = bigint->add( other_bigint )

这会改变bigint实例并返回一个自我引用以允许链接。因此,result_bigint和bigint实际上是同一个实例。这样做是为了确保高性能。当然,也有一个clone()方法,可以生成bigint的副本,允许非侵入性操作。例如,你可以写成:

result_bigint = bigint->clone()->add( other_bigint )

这两个类都已经发布到ABAP Cloud,因此可以在Steampunk、Embedded Steampunk和SAP S/4HANA Cloud中使用。(译者注:虽然我没验证,但可以想象OP版本的7.58也会有

CL_ABAP_BIGINT类具有以下特性:

  • 基本的算术操作,如加法、减法、乘法和带余数的除法
  • 快速克隆操作
  • 快速乘法
  • 高级操作,如最大公约数和整数平方根
  • 数论操作,如质数确定、MOD、POWMOD和MOD_INVERSE
  • 序列化到/从XML/JSON
  • 带千位分隔符的外部表示转换
  • 启用共享内存(仅限非ABAP Cloud)
  • 转换到/从STRING和到DECFLOAT34
  • 适用于ABAP Cloud

CL_ABAP_RATIONAL类几乎具有与CL_ABAP_BIGINT类相同的特性,但是它并未包含那些对有理数来说没有意义的数论函数。

4. 体验如何?

通常,数字计算是使用DECFLOAT34或INT8等内置数据类型进行的。对于相同的任务使用类似乎看似有些不寻常,但实际上非常可读。一个好例子是计算整数平方根的算法,也就是floor(sqrt(n)),如下所示:

class compute_sqrt definition.
public section.
methods compute_sqrt importing number type ref to cl_abap_bigint
returning value(sqrt) type ref to cl_abap_bigint.
endclass. class compute_sqrt implementation.
method compute_sqrt.
data y type ref to cl_abap_bigint.
final(bits) = number->get_number_of_bits( ).
data(x) = cl_abap_bigint=>factory_from_int4( 1 )->mul_by_two_power( ( bits + 2 ) / 2 ).
do.
y = x->clone( )->add( number->clone( )->div( x )-quotient )->div_by_two_power( 1 ).
if y->is_larger_or_equal( x ).
exit.
endif.
x = y.
enddo.
return x.
endmethod.
endclass. start-of-selection.
data(result) = new compute_sqrt( )->compute_sqrt(
cl_abap_bigint=>factory_from_string( `129341967194712394612956129461294861619246` ) ).
cl_demo_output=>display( result->to_string( ) ).

5. 演示程序

任意精度整数库的一个简单演示是RSA算法的实现。RSA是一种被广泛使用的公钥/私钥加密。RSA的每个实现都使用大于一百或一千位精度的大数

有一个演示类CL_DEMO_BIGINT_RSA,以及一个演示报表程序DEMO_BIGINT_RSA,它根据给定的位大小生成公钥/私钥,并使用它加密一条小消息。以前是不可能在纯ABAP中生成RSA公钥/私钥的。以下是纯ABAP实现效果:

还有另一个在CL_DEMO_BIGINT_SQRTDEMO_BIGINT_SQRT中的演示,用于计算自然数的平方根的任意多位数。

6. 何时使用任意精度算术?

可以在以下情况中使用任意精度算术:

  • 真的需要大于34位的大数,因为你的算法需要它。典型的例子就是RSA算法。
  • 有非常大或非常小的数字的计算,不想有任何溢出或下溢。或者,有未知大小的数字的计算,不想关心溢出或下溢。
  • 有复杂的计算,不想关心舍入误差。别忘了:只要坚持使用基本的算术运算,对于任意精度算术,永远不会有任何舍入误差。
  • 使用一些数论算法,如质数检查或模反。

7. ABAP关键字文档和发布说明

可以在以下位置找到更多关于此主题的信息:

参考:ABAP 7.58更新概览

ABAP 7.58 中支持任意精度算术的新类的更多相关文章

  1. 学习PHP中的任意精度扩展函数

    今天来学习的是关于数学方面的第一个扩展.对于数学操作来说,无非就是那些各种各样的数学运算,当然,整个程序软件的开发过程中,数学运算也是最基础最根本的东西之一.不管你是学得什么专业,到最后基本上都会要学 ...

  2. PHP中操作任意精度大小的GMP扩展学习

    对于各类开发语言来说,整数都有一个最大的位数,如果超过位数就无法显示或者操作了.其实,这也是一种精度越界之后产生的精度丢失问题.在我们的 PHP 代码中,最大的整数非常大,我们可以通过 PHP_INT ...

  3. 有意思的RTL函数RegisterClass(在持久化中,你生成的一个新类的对象,系统并不知道他是如何来的,因此需要你注册)good

    例子1:Delphi中使用纯正的面向对象方法(这个例子最直接) Delphi的VCL技术使很多程序员能够非常快速的入门:程序员门只要简单的拖动再加上少量的几个Pascal语句,呵呵,一个可以运行得非常 ...

  4. 支持无限精度无限大数的类BigNumber实现

    介绍 本篇是MathAssist的第二篇,在前言中粗略地展示了MathAssist的“计算和证明”能力,本篇开始将详细介绍其实现原理. 从计算开始说起,要实现任意大数的计算器首先得有一个类支持大数运算 ...

  5. 如何在MQ中实现支持任意延迟的消息?

    什么是定时消息和延迟消息? 定时消息:Producer 将消息发送到 MQ 服务端,但并不期望这条消息立马投递,而是推迟到在当前时间点之后的某一个时间投递到 Consumer 进行消费,该消息即定时消 ...

  6. LINUX任意精度计算器BC用法

    [用途说明] Bash内置了对整数四则运算的支持,但是并不支持浮点运算,而bc命令可以很方便的进行浮点运算,当然整数运算也不再话下.手册页上说bc是An arbitrary precision cal ...

  7. 【OpenGL(SharpGL)】支持任意相机可平移缩放的轨迹球实现

    [OpenGL(SharpGL)]支持任意相机可平移缩放的轨迹球 (本文PDF版在这里.) 在3D程序中,轨迹球(ArcBall)可以让你只用鼠标来控制模型(旋转),便于观察.在这里(http://w ...

  8. Devrama Slider - 支持任意 HTML 的内容滑块

    Devrama Slider 是一个图片滑块,支持很多特色功能.除了支持图片滑动,其它的 HTML 内容也支持.主要特色:响应式.图片预加载.图片延迟加载.进度条.自定义导航栏和控制按钮等等. 在线演 ...

  9. pojg2744找一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。

    http://poj.grids.cn/practice/2744 描述现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是 ...

  10. EntityFramework中支持BulkInsert扩展

    EntityFramework中支持BulkInsert扩展 本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 很显然,你应该不至于使用 Ent ...

随机推荐

  1. 使用MFT进行加密文件传输的7个好处

    至少,托管文件传输(MFT)解决方案是一种产品,它包含入站和出站文件传输的所有方面,同时使用行业标准的网络协议和无缝加密.它可以从单个集中管理点在您的网络,系统,应用程序,贸易伙伴和云环境中自动化和传 ...

  2. java基础 韩顺平老师的 面向对象(高级) 自己记的部分笔记

    373,类变量引出 代码就提到了问题分析里的3点 package com.hspedu.static_; public class ChildGame { public static void mai ...

  3. 学习Source Generators之HelloWorld

    介绍 源生成器是 C# 开发人员可以编写的一种新组件,允许执行两个主要操作: 检索表示正在编译的所有用户代码的编译对象. 可以检查此对象,并且可以编写适用于正在编译的代码的语法和语义模型的代码,就像现 ...

  4. virtualbox安装windows10出现OOBE,卡在OOBE。

    参照 https://zhuanlan.zhihu.com/p/419237209 https://www.0z.gs/win/781.html 文档 https://learn.microsoft. ...

  5. #树状数组,dp#SGU 521 North-East

    题目 在平面上有 \(n\) 个点,现在有一个人要从某个点出发, 每次只能到达横纵坐标都超过原坐标的点,也就是 \(x_j<x_i,y_j<y_i\) 如果他要经过最多的点,那么哪些点是可 ...

  6. #模型转换,动态规划#洛谷 1758 [NOI2009] 管道取珠

    题目 分析 考虑每种情况的方案数平方之和,可以被转换成有两个人同时独立进行该游戏,问最后情况相同的方案数. 那么设 \(dp[i][j][k][o]\) 表示第一个人在上管道拿了 \(i\) 个,下管 ...

  7. #排序,去重#洛谷 5682 [CSPJX2019]次大值

    题目 分析 首先,显然要排序去重,考虑最大值应该是\(a_{n-1}\)(排序后) 那次大值只有可能出现在\(a_{n-2}\)或者\(a_n\bmod a_{n-1}\)中 当然去重后如果只有一个数 ...

  8. C# 中一维数组和二维数组详解

    String[][]是二维数组.例如:String[][] str=new String[4][4],这是创建了一个有bai4行4列元素的数组. String[]代表一维数组.例如:String[]  ...

  9. 【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit

    1.问题描述 在App中供用户在地图上选择地址,目前在使用Map Kit结合geolocationManager逆地理编码时获取的地址信息描述不准确,希望能提供相应的Demo参考. 解决方案 Demo ...

  10. Python smtp发送邮件怎么设置抄送人

    设置抄送人,非常简单,只需要添加一条信息就可以了,例: cc_list = ['xx@xxx.cn', 'xx@xxx.cn'] msg['Cc'] = ','.join(cc_list) smtp. ...