我们正在使用Sonar检查代码的质量,而Sonar找到的代码将float或double的相等性与常量值进行比较,如下所示:
if (x == 0.0) { … }
变量与(0.0
)比较的值是常量,如果变量可以等于此值,则该值也不会计算,只能通过常量设置。这通常用于检查变量是否尚未设置或仍处于初始化状态,例如: G。在值只能为正值的情况下,-1.0
可能会用于“尚未设置”。
因此,由于这些值永远不会计算,而只是从常量设置,因此Sonar投诉对我们没用。仅对于计算值(或者不能精确表示为浮点数或双精度值的断裂值),关于平等测试的投诉才有意义。
我现在的问题是:更改代码的最佳做法是什么,以便Sonar不再抱怨这个?
我看到了几个选项:
(0.0 <= x && x <= 0.0)
或!(x != 0.0)
(目前似乎对Sonar没问题。)Double.doubleToRawLongBits()
比较值的位,如下所示:(Double.doubleToRawLongBits(x) != Double.doubleToRawLongBits(0.0))
。我真的不喜欢这些解决方案,我想,也许,有一个我想不到的更好的解决方案。
答案 0 :(得分:16)
我会选择你的第二个选择:
将Sonar的代码标记为使用特殊装饰器忽略它。
不要成为静态代码分析工具的奴隶。他们并不完美,告诉他们闭嘴没什么不对。我在使用@SuppressLint
等注释时的个人做法是包含一条解释我正在使用注释的注释。
那就是说,我会创建一个常量,所以代码更加不言自明:
private static final double UNINITIALIZED = 0.0;
if (x == UNINITIALIZED) { … }
答案 1 :(得分:4)
这里最好的选择是将问题标记为误报并发表评论。这样,问题和相关的技术债务将从您的SonarQube实例中消失,而不会使用注释污染您的代码。
答案 2 :(得分:2)
如果您仅对未初始化的值使用这些常量和比较,则可以选择将字段设置为Double.NaN
并使用Double.isNaN()
进行比较。 E.g:
double notYetInitialized = Double.NaN;
if (Double.isNaN(notYetInitialized)) {
// handle uninitialized value
}
这使得(某些)读取代码时有意义 - 未初始化的值可能被称为“不是数字”。我无法想象声纳会遇到问题。
答案 3 :(得分:1)
还有正确的方法:
private static final double EPSILON = 0.000000000000001;
if (Math.abs(x) < EPSILON) {
}
答案 4 :(得分:1)
我知道这是一篇非常老的文章,但是我遇到了同样的问题,并使用Equals方法代替了“ ==”运算符。
if (x.Equals(0.0)) { … }
通过这种方式,SonarQube不会抱怨。
再见。
答案 5 :(得分:0)
建议: 一种好方法是使用
BigDecimal
检查等于/不等于0:
BigDecimal balance = pojo.getBalance();//get your BigDecimal obj
0 != balance.compareTo(BigDecimal.ZERO)
说明:
compareTo()
函数将此BigDecimal
与指定的BigDecimal
进行比较。通过此方法,两个BigDecimal
个值相等但具有不同比例(如2.0和2.00)的对象被认为是相等的。优先于六个boolean
比较运算符(<, ==, >, >=, !=, <=)
中的每一个的单独方法提供此方法。执行这些比较的建议惯用法是:(x.compareTo(y) <op> 0)
,其中六个比较运算符之一。
(感谢SonarQube文档)
由于在二进制表示中存储这些值的挑战,浮点数学是不精确的。更糟糕的是,浮点数学不是关联的;通过一系列简单的数学运算推动浮点数或双精度数,由于每一步的舍入,答案将根据这些操作的顺序而有所不同。
即使是简单的浮点分配也不简单:
float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
(结果将根据编译器和编译器设置而有所不同);
因此,在float或double值上使用等于(==)和不等(!=)运算符几乎总是一个错误。相反,最好的方法是完全避免浮点比较。如果无法做到这一点,您应该考虑使用Java的浮点处理数字之一,例如BigDecimal,它可以正确处理浮点比较。第三种选择是不要考虑相等性,而是考虑价值是否足够接近。即比较存储值和期望值之间的差值的绝对值与可接受误差的余量。请注意,这并未涵盖所有情况(例如NaN和Infinity)。
答案 6 :(得分:-1)
如何转换为(int)?
这应该与您想要检查它是否为零的结果相同。
如果您有计算:
double a = c - b
boolean x = (int)(a*100) == 0