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

比较两个相同的“文字”浮点数是否相等是错误的?

宗建章
2023-03-14

这个问题与语言无关,但代码是用Java编写的。

我们都听说过,比较浮点数是否相等通常是错误的。但是,如果我想比较两个完全相同的文字浮点值(或表示转换为浮点数的完全相同的文字值的字符串),该怎么办?

我很确定这些数字是完全相等的(好吧,因为它们在二进制中必须相等——完全相同的东西怎么会产生两个不同的二进制数?!)但我想确定一下。

案例1:

void test1() {
    float f1 = 4.7;
    float f2 = 4.7;
    print(f1 == f2);
}

案例2:

class Movie {
    String rating; // for some reason the type is String
}
void test2() {
    movie1.rating = "4.7";
    movie2.rating = "4.7";

    float f1 = Float.parse(movie1.rating);
    float f2 = Float.parse(movie2.rating);

    print(f1 == f2);
}

在这两种情况下,表达式f1==f2应导致true。我说得对吗?如果它们具有相同的文字浮点值或字符串值,我是否可以安全地比较评级s是否相等?

共有3个答案

巫欣荣
2023-03-14

是的,你可以像这样比较浮动。问题是,即使4.7在转换为浮点数时不是4.7,它也会一致地转换为相同的值。

一般来说,这样比较浮动本身并没有错。但是对于更复杂的数学,你可能需要使用Math.round()或者设置一个“相同”的差异范围,两者应该在这个范围内被算作“相同”。

不动点数也有任意性。例如

1,000,000,001

1.000,000,000

这两个数字不同吗?这取决于你需要的精度。但大多数情况下这些数字在功能上是相同的

须旭
2023-03-14

对相同的编译时常量的计算结果是一致的。

如果你想一想,它们一定是一样的,因为只有一个编译器,它会将文本决定性地转换为它们的浮点表示。

华英睿
2023-03-14

有一条经验法则,您应该应用于所有编程经验法则(经验法则?):

它们过于简单化,如果推进得太远,将导致愚蠢的决策。如果你不能完全理解经验法则背后的意图,你就会陷入困境。也许经验法则仍然是一个净积极因素(不假思索地应用它会改善事情,而不是让事情变得更糟),但它会造成损害,而且无论如何它都不能在辩论中用作论据。

因此,考虑到这一点,很明显,问这个问题是没有意义的:

"鉴于经验法则'不使用==比较浮动'存在,它总是不好吗?"。

答案是非常明显的:嗯,不。这并不总是坏事,因为经验法则基本上是根据定义的,如果不是根据常识的话,永远不会适用。

那么让我们把它分解一下。

为什么有一个经验法则,你不应该==比较浮动?

您的问题表明您已经知道这一点:这是因为对IEEE754概念(如java的doublefloat等)表示的浮点进行任何数学运算都是不精确的(与java的BigDecimal等概念相比,这是精确的*)。

当你面对一条经验法则时,当你摸索经验法则存在的原因并意识到它不适用于你的场景时,做你应该做的事情:完全忽略它。

也许你的问题可以归结为:我想我摸索到了经验法则,但也许我错过了什么;除了“浮点数学引入了会搞砸==比较的小偏差”,这不适用于这种情况,还有其他原因吗这个我不知道的经验法则?

在这种情况下,我的回答是:据我所知,没有。

*)但是BigDecimal有它自己的相等问题,例如:两个BigDecimal对象是否精确地表示同一个数学数,但配置为以不同的比例渲染“相等”?这取决于您的观点是它们是数字还是表示精确小数点的对象,以及一些元属性,包括如何渲染它,以及在明确要求时如何进行取整。值得一提的是,等于BD的实现,它必须做出一个索菲式的选择,并在平等含义的两种同样有效的解释之间进行选择,选择“我代表一个数字”,而不是“我代表一个数元以及一堆元数据”。所有JPA/Hibernate堆栈中都存在相同的sophie选择:JPA对象是否表示“数据库中的一行”(因此,相等仅由主键值定义,如果尚未保存,两个对象不能相等,甚至不能相等,除非具有相同的引用标识),或者它是否表示该行表示的内容,例如,一名学生,而不是“数据库中代表一名学生的一行”,在这种情况下,unid是一个与身份无关的字段,而所有其他字段(姓名、生日、社会保险号等)都是。平等是困难的。

 类似资料:
  • 比较两个NumPy数组是否相等的最简单方法是什么(其中相等定义为:A=B iff,用于所有索引i:

  • 我做了这个扩展方法来检查一个类型是否实现了一个接口。要使其正常工作,它需要比较两种类型。然而,这种比较似乎并不现实: 这是我比较失败的情况: 正如注释中提到的,如果我比较类型名,那么它总是按照预期工作。我想知道这是怎么回事。

  • 本文向大家介绍JavaScript比较两个对象是否相等的方法,包括了JavaScript比较两个对象是否相等的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript比较两个对象是否相等的方法。分享给大家供大家参考。具体如下: 在Python中可以通过cmp()内建函数来比较两个对象所包涵的数据是否相等(数组、序列、字典)。但是在javascript语言中并没有相关的实现。

  • 问题内容: 比较两个NumPy数组是否相等的最简单方法是什么(其中相等定义为:对于所有索引i:,A = B iff )? 简单地使用就会给我一个布尔数组: 我是否必须确定该数组的元素是否相等,或者是否有更简单的比较方法? 问题答案: 测试数组(A == B)的所有值是否均为True。 注意:也许您还想测试A和B形状,例如 特殊情况和替代方法 (来自dbaupp的回答和yoavram的评论) 应当指

  • 如何比较两个javascript集?我尝试使用和但都返回false。 这两个集合是等价的,因为根据定义,集合没有顺序(至少通常没有)。我看了MDN上的集合的留档,没有发现任何有用的东西。有人知道怎么做吗?

  • 本文向大家介绍Java比较两个List的值是否相等的方法,包括了Java比较两个List的值是否相等的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java比较两个List的值是否相等的方法。分享给大家供大家参考。具体如下: 假设两个队列 {1,2,3,4} 和 {4,3,2,1} ,这个方法用来比较这两个队列中包含的值是否相等 希望本文所述对大家的java程序设计有所帮助。