当前位置: 首页 > 知识库问答 >
问题:

以小数为单位的BigDecimal

韦望
2023-03-14

我在斯卡拉偶然发现了intersting这个东西(可能只对我来说)。总而言之,如果我们有一个BigDecimal(假设vala=BigDeximal(someValue),其中someValue是十进制字符串)

N * a / N == a

不会总是产生< code>true。我认为它与大小数的运算有关。我知道在scala中,创建BigDecimals的默认MathContext设置为< code>DECIMAL128(四舍五入,精度等于34)。我在小数点后超过30位的小数上发现了这种行为

我的问题是为什么我会得到这样的结果。我能控制他们吗?

例子

-0.007633587786259541984732824427480916

共有1个答案

郭远
2023-03-14

正如之前的评论已经指出的那样,对于无理数来说,这是不可避免的。这是因为没有办法使用标准数值类型(如果有的话)来表示无理数。由于我没有无理数的例子(即使 PI 也仅限于固定位数,因此可以表示为 2 个整数的商,使其成为有理数),我将使用重复的小数来说明这个问题。我将 N*a/N 更改为 a/N*N,因为它更好地展示了整数的问题,但它们是等价的:

a = BigDecimal(1)
N = BigDecimal(3)
a/N = 0.333...
a/N*N = 0.999...

正如您在上面的示例中所看到的,您可以使用尽可能多的小数位和任何舍入模式,但结果永远不会等于 1。(虽然每个操作使用不同的舍入模式可以获得 1,即 BigDecimal(3, roundHalfEven) * (BigDecimal(1, roundUp) / 3))

为了控制数字比较,您可以做的一件事是在执行算术运算时使用更高的精度,并在比较时四舍五入到所需的(较低的)精度:

val HighPrecision = new java.math.MathContext(36, java.math.RoundingMode.HALF_EVEN);
val TargetPrecision = java.math.MathContext.DECIMAL128;

val a = BigDecimal(1, HighPrecision)
val N = BigDecimal(3, HighPrecision)
(a/N*N).round(TargetPrecision) == a.round(TargetPrecision)

在上面的示例中,最后一个表达式的计算结果为 true

更新

为了回答您的评论,虽然BigDecimal是任意精度,但它仍然受到精度的限制。它可以是34,也可以是1000000(如果您有足够的内存)。BigDecimal不知道1/30.33

 类似资料:
  • 问题内容: 我有一个对象。我使用将对象编码为json 。 我怎样才能测量json字符串的大小? 问题答案: 并且不公开也不维护写入字节数。 一种方法是先使用内置函数将其编入其长度来封送该值。您要查找的位数是长度乘以8(1字节为8位)。之后,您必须手动将字节片写入输出中。对于小型类型,这不是问题,但是对于大型结构/值,可能是不希望的。另外,也没有必要的工作将其编组,获取其长度并手动编写切片。 一种更

  • 我想得到的是: 是否可以强制excel将“30378”视为秒数而不是天数?我知道我可以把'00:00:30378'写进一个牢房--这是唯一的办法吗?

  • Java8的类有一个方法,,它允许您从、字母字符串中定义格式。这些示例没有阐明,年-纪元和,周-年之间的区别。是什么?

  • 问题内容: 给定matplotlib中的一组轴,是否有办法确定其像素大小?我需要根据调整大小来调整大小,以适应更大或更小的数字。 (特别是我想更改线宽,使其与轴的大小成比例。) 问题答案: 这给出了以英寸为单位的宽度和高度。 这可能足以满足您的目的,但是要获得像素,可以乘以: 例如, 要制作与该图形大小完全相同的图像,必须删除图形与轴之间的空格:

  • 问题内容: 我希望找到如何获取OracleDB中结果集的kb大小。我不是系统管理员,但是经常运行返回超过10万行的查询,因此我需要找到一种确定总kb大小的方法。谢谢你 问题答案: 在SQL * Plus中: 要使用AUTOTRACE,需要PLUSTRACE角色,默认情况下不会授予该角色。了解更多。

  • 问题内容: 目前,我正在记录东西,并且正在使用带有自定义的格式化程序: 我的问题是微秒为六位数。无论如何,是否需要吐出更少的数字,例如微秒的前三个数字? 问题答案: 最简单的方法是使用切片将微秒的最后三位数字切掉: 我强烈建议切碎。我曾经写过一些对时间戳进行四舍五入而不是四舍五入的记录代码,当四舍五入改变了最后一位时,我发现它实际上有点令人困惑。定时代码在某个时间戳记时停止运行,但是由于舍入的缘故