java - 解释为什么这可以找到两个等于小数点后三位的数字
问题描述
试图理解为什么这段代码可以找到两个等于小数点后三位的数字。
铸造(int)让我措手不及(无法绕开我的头).....
public static boolean areEqualByThreeDecimalPlaces(double firstValue, double secondValue) {
int moveThreeDecimalPlacesToRight = (int) Math.pow(10, 3);
return (int) (firstValue * moveThreeDecimalPlacesToRight) == (int) (secondValue * moveThreeDecimalPlacesToRight);
}
解决方案
首先请查看规范并了解强制转换表达式的工作原理。
根据该章,这里有一个简短的总结:
intValue
*doubleValue
将是一个double
- 您可以转换(在这种情况下向下转换)类型,因此
(int)(doubleValue * intValue)
将被转换为int
- 如果您明确地将 a
double
转换为,int
您将丢失小数。
现在让我们逐步分析该代码。
//Just for the example let fisrtValue is 123.456789 and secondValue is 123.456999
double firstValue = 123.456789
double secondValue = 123.456999
(firstValue * moveThreeDecimalPlacesToRight)
// 123.456789 * 1000 will be a double 123456.789
(secondValue * moveThreeDecimalPlacesToRight)
// 123.456999 * 1000 will be a double 123456.999
return 123456.789 == 123456.999 will always return false
(int) (firstValue * moveThreeDecimalPlacesToRight)
// 123.456789 * 1000 will be an int 123456
(int) (secondValue * moveThreeDecimalPlacesToRight)
// 123.456999 * 1000 will be an int 123456
最后
return (int) (firstValue * moveThreeDecimalPlacesToRight) == (int) (secondValue * moveThreeDecimalPlacesToRight);
// return 123456 == 123456 will return true
public static boolean areEqualByThreeDecimalPlaces(double firstValue, double secondValue) {
// Math.pow(...) retuns a double so it have to downcast to int
int moveThreeDecimalPlacesToRight = (int) Math.pow(10, 3);
/*
* We don't care about just the first three decimal places
* If fisrtValue is 123.456789 then
* firstValue * moveThreeDecimalPlacesToRight will be 123456.789
* and secondValue * moveThreeDecimalPlacesToRight will be 123456.999
* so both of them must be downcasted to int
* because 123456.789 will never be equal to 123456.999
*/
return (int) (firstValue * moveThreeDecimalPlacesToRight) == (int) (secondValue * moveThreeDecimalPlacesToRight);
}
更新
按照@Eritrean 的建议,我不得不提到这是一个非常糟糕的主意。根据转换规范更精确地缩小原始转换部分:
缩小原语转换可能会丢失有关数值整体大小的信息,也可能会丢失精度和范围。
因此,如果您有一个大的 double 数字被向下转换为 int 那么您的方法可以返回误报值。
我刚刚找到了两个(或更多)更好的选择来解决您的问题:
- 一个很好的解释如何在没有 3rd 方库的情况下做到这一点:https ://stackoverflow.com/a/2944352/5043481
- Apache Commons 有可以帮助您的实用程序类:http ://commons.apache.org/proper/commons-math/javadocs/api-3.6/index.html?org/apache/commons/math3/util/Precision.html
推荐阅读
- python - 尝试读取 .py 文件并创建 .mp4 输出时出现 CMD/Python 语法错误
- curl - 使用 curl 将不记名授权标头传递给 AWS 函数
- reactjs - 尽管 TypeScript 编译器错误,为什么我的 React Native 应用程序构建成功?
- sql - 在 where 子句中使用这个子查询的语法问题是什么
- c - 如何将格式化数据添加到 printf() 调用
- java - 'Dcoder' 练习失败的测试用例
- python - 如何在谷歌应用脚本中更新 mailgun 路由
- php - “无法读取数据,因为它的格式不正确” IOS 使用 swift 和 MySQL 数据库的登录系统
- ansible - 在 k8s_facts 模块上没有观察到输出
- xslt - Report_Entry(worker) 的第一行需要默认为“YES”。工人返回“NO”的所有其他行