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. C# 人脸比对服务,自带模型,离线部署

    软件说明 基于以下开源项目,做了再次封装 GitHub - ViewFaceCore/ViewFaceCore: C# 超简单的离线人脸识别库.( 基于 SeetaFace6 ) 可以一键开启服务: ...

  2. PLSQL的异常传播

    文章概要: 本文对主要就PLSQL的异常传播进行知识性小结,分为四个部分,PLSQL异常传播小结,编写小案例验证5种传播规则,示例了一个容易理解出错的案例,以及使用goto结合异常处理的案例. 一,异 ...

  3. Kingbase 函数查询返回结果集

    数据库使用过成中,时常会遇到需要返回一个结果集的情况,如何返回一个结果集,以及如何选择一个合适的方式返回结果集,是现场经常需要考虑的问题. 下面介绍KingbaseES中各种返回结果集的方式. 1.通 ...

  4. WPF实现树形表格控件(TreeListView)

    前言 本文将探讨如何利用WPF框架实现树形表格控件,该控件不仅能够有效地展示复杂的层级数据,还能够提供丰富的个性化定制选项.我们将介绍如何使用WPF提供的控件.模板.布局.数据绑定等技术来构建这样一个 ...

  5. 2 URLEncode和Base64

    1. URLEncode和Base64 在我们访问一个url的时候总能看到这样的一种url https://www.sogou.com/web?query=%E5%90%83%E9%A5%AD%E7% ...

  6. CentOS 9 安装 Nginx 模块 `subs_filter`

    sub_filter 和 subs_filter 区别 sub_filter( 0.7.24):替换响应体(Response Body)中的文本,只能设置一组替换. subs_filter:替换响应体 ...

  7. 基于ArkUI框架开发-ImageKnife渲染层重构

      ImageKnife是一款图像加载缓存库,主要功能特性如下: ●支持内存缓存,使用LRUCache算法,对图片数据进行内存缓存. ●支持磁盘缓存,对于下载图片会保存一份至磁盘当中. ●支持进行图片 ...

  8. 赋能千行百业数字化转型,OpenHarmony生态新成果即将亮相HDC2022

     第四届华为开发者大会 2022(Together)将于11月4日-6日在东莞召开,OpenAtom OpenHarmony(以下简称"OpenHarmony")将携生态新成果亮相 ...

  9. jenkins安装卸载和下载

    环境 :docker容器 卸载 jenkins 1.rpm卸载rpm -e jenkins 2.检查是否卸载成功rpm -ql jenkins 3.彻底删除残留文件:find / -iname jen ...

  10. openGauss数据库源码学习-指标采集、预测与异常检测

    opengauss 源码解析 指标采集.预测与异常检测 代码位置:/gausskernel/dbmind/tools/anomaly_detection 各模组在整体结构上的组合在摩天轮论坛上官方解析 ...