【发布时间】:2023-10-10 07:45:01
【问题描述】:
所以:
//aValue = 4.45
//bValue = 4.35
//maxValueDiff = 0.1
//The absolute value of a - b = 0.1
if( Math.abs(aValue - bValue) <= maxValueDiff ) return true;
logger.info("valueDiffCheck a:" + aValue +" b:"+ bValue + " e1:" + maxValueDiff);
为什么我会在我的日志中看到这个:
valueDiffCheck a:4.45 b:4.35 e1:0.1
怀疑这是因为 Double 是不准确的双重痛苦,但如果是这种情况,我不应该看到吗?喜欢它应该打印 0.1 实际上是 0.10000000111 还是什么? ...或者打印格式有什么讨厌的地方?
目标代码具有大量数据的高性能,因此我们不想使用 BigDecimal。确保 0.44 是 0.44 的下一个最佳方法是什么?
好的,让我明确声明我们只需要两位小数。使用 BigDecimal 所涉及的准确性是主要的矫枉过正。
【问题讨论】:
-
如果您想要更高的精度,则必须使用更大的小数来比较。减法和加法虽然不是问题。如果你担心精度问题,你应该更关心除法。
-
@Luminous,“不知道“减法和加法不是问题”是什么意思。 c 不等于实数 c',即 a 和 b 的实际总和。c 和 c' 之间的差值可能高达一个 ULP 的 1/2。
-
实际上,它打印正确。你应该打印的是 Math.abs(aValue - bValue)
-
写了一个简短的单元测试,这是导致不准确的数学。我只需要两位小数。结果证明是愚蠢的,比如 0.1000000000000123
-
请阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic。这个问题每周在 SO 上出现几次。简单的答案是,不使用精确的十进制算术(即
BigDecimal)是不可能的。
标签: java double rounding truncate