Java基本的程序结构设计 大数操作

Posted 张小贱1987

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基本的程序结构设计 大数操作相关的知识,希望对你有一定的参考价值。

大数操作

BigInteger

不可变的任意精度的整数。所有操作中,都以二进制补码形式表示 BigInteger(如 Java 的基本整数类型)。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。

个人理解:可以理解为BigInteger内部维护了一个int数组,这个数组可以无限大。java在对BigInteger进行运算的时候,实际上是对数组的二进制进行补码运算。

算术运算的语义完全模仿 Java 整数算术运算符的语义,如 The Java Language Specification 中所定义的。例如,以零作为除数的除法抛出 ArithmeticException,而负数除以正数的除法则产生一个负(或零)的余数。Spec 中关于溢出的细节都被忽略了,因为 BigIntegers 所设置的实际大小能适应操作结果的需要。

BigInteger和BigDecimal都是不可变的,每次执行加减乘除操作都会生成新的对象,不能修改自身。

BigDecimal

不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)

个人理解:可以理解为,BigDecimal是通过BigInteger和标度实现的,如12346789.12346789,这样一个数值,其实是1234678912346789和10的-9次方。也就是说,通过1234678912346789这样一个BigInteger和-9来实现了BigDecimal。

BigInteger的使用场景不太多,大部分情况下,long应该足够了,但是由于double和float的精度问题,所以BigDecimal是会使用到的。

下面是BigDecimal的JAVA API描述。

BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。toString() 方法提供 BigDecimal 的规范表示形式。

BigDecimal 类使用户能完全控制舍入行为。如果未指定舍入模式,并且无法表示准确结果,则抛出一个异常;否则,通过向该操作提供适当的 MathContext 对象,可以对已选择的精度和舍入模式执行计算。在任何情况下,可以为舍入控制提供八种舍入模式。使用此类(例如,ROUND_HALF_UP)中的整数字段来表示舍入模式已过时;应改为使用 RoundingMode enum(例如,RoundingMode.HALF_UP)的枚举值。

当为 MathContext 对象提供 0 的精度设置(例如,MathContext.UNLIMITED)时,算术运算是准确的,它们是不采用任何 MathContext 对象的算术方法。(这是第 5 版之前的版本支持的惟一行为。)为了计算准确结果,不使用附带 0 精度设置的 MathContext 对象的舍入模式设置,因此与该对象无关。在除法中,准确的商可能是一个无限长的十进制扩展;例如,1 除以 3 所得的商。如果商具有无穷的十进制扩展,但是指定了该操作返回准确结果,则抛出 ArithmeticException。否则,像其他操作那样,返回除法运算的准确结果。

当精度设置不为 0 时,BigDecimal 算法的规则完全符合 ANSI X3.274-1996 和 ANSI X3.274-1996/AM 1-2000( 7.4 节)中定义的算法的可选操作模式。与上述标准不同,BigDecimal 包括多种舍入模式,它们对于版本 5 以前的 BigDecimal 版本中的除法是强制性的。这些 ANSI 标准和 BigDecimal 规范之间的任何冲突都按照有利于 BigDecimal 的方式进行解决。

由于同一数值可以有不同的表示形式(具有不同的标度),因此运算和舍入的规则必须同时指定数值结果和结果表示形式中所用的标度。

一般情况下,当准确结果(在除法中,可能有无限多位)比返回的数值具有更多位数时,舍入模式和精度设置确定操作如何返回具有有限位数的结果。 首先,MathContext 的 precision 设置指定要返回的总位数;这确定了结果的精度。位数计数从准确结果的最左边的非零数字开始。舍入模式确定丢弃的尾部位数如何影响返回的结果。

对于所有算术运算符,运算的执行方式是,首先计算准确的中间结果,然后,使用选择的舍入模式将其舍入为精度设置(如有必要)指定的位数。如果不返回准确结果,则将丢弃准确结果的某些数位。当舍入增加了返回结果的大小时,前导数字"9"的进位传播可能会创建新的数位。例如,将值 999.9 舍入为三位数字,则在数值上等于一千,表示为 100×101。在这种情况下,新的 "1" 是返回结果的前导数位。

除了逻辑的准确结果外,每种算术运算都有一个表示结果的首选标度。下表列出了每个运算的首选标度。

算术运算结果的首选标度

运算

结果的首选标度

max(addend.scale(), augend.scale())

max(minuend.scale(), subtrahend.scale())

multiplier.scale() + multiplicand.scale()

dividend.scale() - divisor.scale()

这些标度是返回准确算术结果的方法使用的标度;准确相除可能必须使用较大的标度除外,因为准确的结果可能有较多的位数。例如,1/32 得到 0.03125。

舍入之前,逻辑的准确中间结果的标度是该运算的首选标度。如果用 precision 位数无法表示准确的数值结果,则舍入会选择要返回的一组数字,并将该结果的标度从中间结果的标度减小到可以表示实际返回的 precision 位数的最小标度。如果准确结果可以使用最多 precision 个数字表示,则返回具有最接近首选标度的标度的结果表示形式。尤其是,通过移除结尾零并减少标度,可以用少于 precision 个数字来表示准确的可表示的商。例如,使用 floor 舍入模式将结果舍入为三个数字,
19/100 = 0.19 // integer=19, scale=2
但是
21/110 = 0.190 // integer=190, scale=3

注意,对于加、减和乘,标度的缩减量将等于丢弃的准确结果的数字位置数。如果舍入导致进位传播创建一个新的高位,则当未创建新的数位时,会丢弃该结果的附加数字。

其他方法可能与舍入语义稍微不同。例如,使用指定的算法的 pow 方法得到的结果可能偶尔不同于舍入得到的算术结果,如最后一位有多个单位(ulp)。

可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScaleround)返回 BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeftmovePointRight)返回从操作数创建的 BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。

为了简洁明了起见,整个 BigDecimal 方法的描述中都使用了伪代码。伪代码表达式 (i + j) 是"其值为 BigDecimal i 加 BigDecimal j 的 BigDecimal"的简写。伪代码表达式 (i == j) 是"当且仅当 BigDecimal i 表示与 BigDecimal j 相同的值时,则为 true"的简写。可以类似地解释其他伪代码表达式。方括号用于表示特定的 BigInteger 和定义 BigDecimal 值的标度对;例如,[19, 2] 表示 BigDecimal 在数值上等于 0.19,标度是 2。

注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素,则应特别小心,因为 BigDecimal 的自然排序与 equals 方法不一致。有关更多信息,请参见 ComparableSortedMapSortedSet

当为任何输入参数传递 null 对象引用时,此类的所有方法和构造方法都将抛出 NullPointerException。

常用API:

BigDecimal(BigInteger val)
将 BigInteger 转换为 BigDecimal。

BigDecimal(BigInteger unscaledVal, int scale)
将 BigInteger 非标度值和 int 标度转换为 BigDecimal。

BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
将 BigInteger 非标度值和 int 标度转换为 BigDecimal(根据上下文设置进行舍入)。

BigDecimal(BigInteger val, MathContext mc)
将 BigInteger 转换为 BigDecimal(根据上下文设置进行舍入)。

BigDecimal(char[] in)
将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列。

BigDecimal(char[] in, int offset, int len)
将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列,同时允许指定子数组。

BigDecimal(char[] in, int offset, int len, MathContext mc)
将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列,同时允许指定子数组,并根据上下文设置进行舍入。

BigDecimal(char[] in, MathContext mc)
将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列(根据上下文设置进行舍入)。

BigDecimal(double val)
将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。

BigDecimal(double val, MathContext mc)
将 double 转换为 BigDecimal(根据上下文设置进行舍入)。

BigDecimal(int val)
将 int 转换为 BigDecimal。

BigDecimal(int val, MathContext mc)
将 int 转换为 BigDecimal(根据上下文设置进行舍入)。

BigDecimal(long val)
将 long 转换为 BigDecimal。

BigDecimal(long val, MathContext mc)
将 long 转换为 BigDecimal(根据上下文设置进行舍入)。

BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。

BigDecimal(String val, MathContext mc)
将 BigDecimal 的字符串表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符串(按照上下文设置进行舍入)。

 

BigDecimal

abs()
返回 BigDecimal,其值为此 BigDecimal 的绝对值,其标度为 this.scale()。

BigDecimal

abs(MathContext mc)
返回其值为此 BigDecimal 绝对值的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

add(BigDecimal augend)
返回一个 BigDecimal,其值为 (this + augend),其标度为 max(this.scale(), augend.scale())。

BigDecimal

add(BigDecimal augend, MathContext mc)
返回其值为 (this + augend) 的 BigDecimal(根据上下文设置进行舍入)。

byte

byteValueExact()
将此 BigDecimal 转换为 byte,以检查丢失的信息。

int

compareTo(BigDecimal val)
将此 BigDecimal 与指定的 BigDecimal 比较。

BigDecimal

divide(BigDecimal divisor)
返回一个 BigDecimal,其值为 (this / divisor),其首选标度为 (this.scale() - divisor.scale());如果无法表示准确的商值(因为它有无穷的十进制扩展),则抛出 ArithmeticException。

BigDecimal

divide(BigDecimal divisor, int roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。

BigDecimal

divide(BigDecimal divisor, int scale, int roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。

BigDecimal

divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。

BigDecimal

divide(BigDecimal divisor, MathContext mc)
返回其值为 (this / divisor) 的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

divide(BigDecimal divisor, RoundingMode roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。

BigDecimal[]

divideAndRemainder(BigDecimal divisor)
返回由两个元素组成的 BigDecimal 数组,该数组包含 divideToIntegralValue 的结果,后跟对两个操作数计算所得到的 remainder。

BigDecimal[]

divideAndRemainder(BigDecimal divisor, MathContext mc)
返回由两个元素组成的 BigDecimal 数组,该数组包含 divideToIntegralValue 的结果,后跟根据上下文设置对两个操作数进行舍入计算所得到的 remainder 的结果。

BigDecimal

divideToIntegralValue(BigDecimal divisor)
返回 BigDecimal,其值为向下舍入所得商值 (this / divisor) 的整数部分。

BigDecimal

divideToIntegralValue(BigDecimal divisor, MathContext mc)
返回 BigDecimal,其值为 (this / divisor) 的整数部分。

double

doubleValue()
将此 BigDecimal 转换为 double。

boolean

equals(Object x)
比较此 BigDecimal 与指定的 Object 的相等性。

float

floatValue()
将此 BigDecimal 转换为 float。

int

hashCode()
返回此 BigDecimal 的哈希码。

int

intValue()
将此 BigDecimal 转换为 int。

int

intValueExact()
将此 BigDecimal 转换为 int,以检查丢失的信息。

long

longValue()
将此 BigDecimal 转换为 long。

long

longValueExact()
将此 BigDecimal 转换为 long,以检查丢失的信息。

BigDecimal

max(BigDecimal val)
返回此 BigDecimal 和 val 的最大值。

BigDecimal

min(BigDecimal val)
返回此 BigDecimal 和 val 的最小值。

BigDecimal

movePointLeft(int n)
返回一个 BigDecimal,它等效于将该值的小数点向左移动 n 位。

BigDecimal

movePointRight(int n)
返回一个 BigDecimal,它等效于将该值的小数点向右移动 n 位。

BigDecimal

multiply(BigDecimal multiplicand)
返回一个 BigDecimal,其值为 (this × multiplicand),其标度为 (this.scale() + multiplicand.scale())。

BigDecimal

multiply(BigDecimal multiplicand, MathContext mc)
返回其值为 (this × multiplicand) 的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

negate()
返回 BigDecimal,其值为 (-this),其标度为 this.scale()。

BigDecimal

negate(MathContext mc)
返回其值为 (-this) 的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

plus()
返回 BigDecimal,其值为 (+this),其标度为 this.scale()。

BigDecimal

plus(MathContext mc)
返回其值为 (+this) 的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

pow(int n)
返回其值为 (thisn) 的 BigDecimal,准确计算该幂,使其具有无限精度。

BigDecimal

pow(int n, MathContext mc)
返回其值为 (thisn) 的 BigDecimal。

int

precision()
返回此 BigDecimal 的精度。

BigDecimal

remainder(BigDecimal divisor)
返回其值为 (this % divisor) 的 BigDecimal。

BigDecimal

remainder(BigDecimal divisor, MathContext mc)
返回其值为 (this % divisor) 的 BigDecimal(根据上下文设置进行舍入)。

BigDecimal

round(MathContext mc)
返回根据 MathContext 设置进行舍入后的 BigDecimal。

int

scale()
返回此 BigDecimal 的标度。

BigDecimal

scaleByPowerOfTen(int n)
返回其数值等于 (this * 10n) 的 BigDecimal。

BigDecimal

setScale(int newScale)
返回一个 BigDecimal,其标度为指定值,其值在数值上等于此 BigDecimal 的值。

BigDecimal

setScale(int newScale, int roundingMode)
返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。

BigDecimal

setScale(int newScale, RoundingMode roundingMode)
返回 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。

short

shortValueExact()
将此 BigDecimal 转换为 short,以检查丢失的信息。

int

signum()
返回此 BigDecimal 的正负号函数。

BigDecimal

stripTrailingZeros()
返回数值上等于此小数,但从该表示形式移除所有尾部零的 BigDecimal。

BigDecimal

subtract(BigDecimal subtrahend)
返回一个 BigDecimal,其值为 (this - subtrahend),其标度为 max(this.scale(), subtrahend.scale())。

BigDecimal

subtract(BigDecimal subtrahend, MathContext mc)
返回其值为 (this - subtrahend) 的 BigDecimal(根据上下文设置进行舍入)。

BigInteger

toBigInteger()
将此 BigDecimal 转换为 BigInteger。

BigInteger

toBigIntegerExact()
将此 BigDecimal 转换为 BigInteger,以检查丢失的信息。

String

toEngineeringString()
返回此 BigDecimal 的字符串表示形式,需要指数时,则使用工程计数法。

String

toPlainString()
返回不带指数字段的此 BigDecimal 的字符串表示形式。

String

toString()
返回此 BigDecimal 的字符串表示形式,如果需要指数,则使用科学记数法。

BigDecimal

ulp()
返回此 BigDecimal 的 ulp(最后一位的单位)的大小。

BigInteger

unscaledValue()
返回其值为此 BigDecimal 的非标度值 的 BigInteger。

static BigDecimal

valueOf(double val)
使用 Double.toString(double) 方法提供的 double 规范的字符串表示形式将 double 转换为 BigDecimal。

static BigDecimal

valueOf(long val)
将 long 值转换为具有零标度的 BigDecimal。

static BigDecimal

valueOf(long unscaledVal, int scale)
将 long 非标度值和 int 标度转换为 BigDecimal。

 

关于:MathContext

该对象是封装上下文设置的不可变对象,它描述数字运算符的某些规则,例如由 BigDecimal 类实现的规则。

基本独立设置为:

precision:某个操作使用的数字个数;结果舍入到此精度

roundingMode:一个 RoundingMode 对象,该对象指定舍入使用的算法。

字段摘要

static MathContext

DECIMAL128
一个 MathContext 对象,其精度设置与 IEEE 754R Decimal128 格式(即 34 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式。

static MathContext

DECIMAL32
一个 MathContext 对象,其精度设置与 IEEE 754R Decimal32 格式(即 7 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式。

static MathContext

DECIMAL64
一个 MathContext 对象,其精度设置与 IEEE 754R Decimal64 格式(即 16 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式。

static MathContext

UNLIMITED
其设置具有无限精度算法所需值的 MathContext 对象。

 

构造方法摘要

MathContext(int setPrecision)
使用指定的精度和 HALF_UP 舍入模式构造一个新的 MathContext。

 

MathContext(int setPrecision, RoundingMode setRoundingMode)
使用指定的精度和舍入模式构造一个新的 MathContext。

 

MathContext(String val)
从一个字符串构造一个新的 MathContext。

 

 

 

枚举 RoundingMode

为可能丢弃精度的数值操作指定一种舍入行为。每种舍入模式都指示如何计算返回舍入结果位数的最低有效位。如果返回的位数比表示精确数值结果所需的位数少,则舍弃的位数称为舍弃部分,而不管这些位数对数值的作用如何。换句话说,假设是一个数值,舍弃部分的绝对值可能大于 1。

每种舍入模式的描述包括一个表,列出如何在相关的舍入模式下将不同的两位十进制数舍入为一位十进制数。表中的结果栏可以通过以下方式获得:使用指定的值创建一个 BigDecimal 数字,形成一个具有适当设置(precision 设置为 1,roundingMode 设置为相关的舍入模式)的 MathContext 对象,并使用适当的 MathContext 对此数字调用 round。下面是一个汇总表,该表显示了在所有舍入模式下这些舍入操作的结果。

枚举常量摘要

CEILING
向正无限大方向舍入的舍入模式。

 

DOWN
向零方向舍入的舍入模式。

 

FLOOR
向负无限大方向舍入的舍入模式。

 

HALF_DOWN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。

 

HALF_EVEN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

 

HALF_UP
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。

 

UNNECESSARY
用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。

 

UP
远离零方向舍入的舍入模式。

 

 

根据给定的舍入模式将输入数字舍入为一位数的结果,不同舍入模式下的舍入操作汇总:

输入数字

UP

DOWN

CEILING

FLOOR

HAL

F_UP

HALF

_DOWN

HALF

_EVEN

UNNECE

SSARY

5.5

6

5

6

5

6

5

6

Arithmetic

Exception

2.5

3

2

3

2

3

2

2

Arithmetic

Exception

1.6

2

1

2

1

2

2

2

Arithmetic

Exception

1.1

2

1

2

1

1

1

1

Arithmetic

Exception

1.0

1

1

1

1

1

1

1

1

-1.0

-1

-1

-1

-1

-1

-1

-1

-1

-1.1

-2

-1

-1

-2

-1

-1

-1

Arithmetic

Exception

-1.6

-2

-1

-1

-2

-2

-2

-2

Arithmetic

Exception

-2.5

-3

-2

-2

-3

-3

-2

-2

Arithmetic

Exception

-5.5

-6

-5

-5

-6

-6

-5

-6

Arithmetic

Exception


 
































































































以上是关于Java基本的程序结构设计 大数操作的主要内容,如果未能解决你的问题,请参考以下文章

Scala基本语法及操作程序控制结构

JavaSE-基本程序设计结构(下)

Java基本的程序结构设计 字符类型

大数运算之 Java BigInteger 的基本用法

java之理解面向对象

链表实现大数类阶乘