【问题标题】:Bijection between Java float and integer keeping orderJava浮点数和整数保持顺序之间的双射
【发布时间】:2014-07-26 20:55:28
【问题描述】:

Java 中的 intfloat 都是 32 位大小的值。是否可以编写一对函数

int toInt(float f);
float toFloat(int n);

如果f1f2 是任意的float 非NaN 值并且i1 和i2 是任意的int 值:

  • f1 < f2 当且仅当 toInt(f1) < toInt(f2)
  • f1 > f2 当且仅当 toInt(f1) > toInt(f2)
  • f1 == f2 当且仅当 toInt(f1) == toInt(f2)
  • toInt(toFloat(i1) == i1
  • toFloat(toInt(f1)) == f1

编辑:我已经编辑了问题以排除浮点数的 NaN 值,这要感谢澄清这些问题的答案。

【问题讨论】:

    标签: java casting int


    【解决方案1】:

    是的。 IEEE floats 和双精度的排列方式使您可以通过对原始二进制表示进行 unsigned 比较来比较它们。将浮点数转换为原始整数并返回的函数是java.lang.Float.floatToIntBitsjava.lang.Float.intBitsToFloat。这些函数是处理器内在函数,因此它们的成本极低。

    long 和 double 也是如此。这里的转换函数是java.lang.Double.doubleToLongBitsjava.lang.Double.longBitsToDouble

    请注意,如果您想对整数使用普通的有符号比较,除了转换为整数之外,您还必须进行一些额外的转换。

    此规则的唯一例外是 NaN,它无论如何都不允许全排序。

    【讨论】:

    • x ^ Integer.MIN_VALUEy ^ Integer.MIN_VALUE 的有符号比较等效于 xy 的无符号比较。
    【解决方案2】:

    你可以使用

    int n = Float.floatToRawIntBits(f);
    
    float f2 = Float.intBitToFloat(n);
    
    int n2 = Float.floatToRawIntBits(f2);
    
    assert n == n2; // always
    assert f == f2 || Float.isNaN(f);
    

    作为int 的原始位与原始float 具有相同的排序顺序,但与float 值不可比较的NaN 值除外,其值为int

    注意:NaN 有多个值,它们不等于float

    【讨论】:

      【解决方案3】:

      不,你不能

      有 2^32 个可能的 int 值,它们都是不同的。 但是,它们少于 2^32 个浮点数; IE。 7FF0000000000001 到 7FF7FFFFFFFFFFFF 代表 NaN,

      因此,您的整数比浮点数多,因此无法将它们明确地相互映射,因为 toFloat(i1) 不会为每个整数生成不同的浮点数

      【讨论】:

      • 从技术上讲,存在多个 NaN 值,因此即使无法判断为 float 值,也会保留此范围内的 int
      【解决方案4】:

      我明白你在说什么。起初我对你的问题有不同的解释。正如其他人提到的那样:是的。使用herehere 描述的文章来解释为什么我们应该使用@Peter Lawrey 描述的方法来比较整数和浮点数之间的底层位模式

      【讨论】:

      【解决方案5】:

      Rüdiger Klaehn 的回答给出了正常情况,但缺少一些细节。双射仅在 nice and clean 浮点数的域中存在。

      注意:IEEE 浮点数的表示是sign_bit(1 bit) exponent(8 bits) sinificand(23 bits),值是:(-1)<sup>sign</sup> * 2<sup>exp</sup> * significandclean 的情况下。实际上,23位代表实际有效位的小数部分,整数部分为1。

      对于0 < exp < 255(对应于 normal 而不是空浮点数)作为无符号字节并且在该域中你有一个双射,一切都很好。

      对于exp == 255,您的无限值是significand == 0,而significand != 0 的所有NaN - 好的,您明确排除了它们。

      但是对于exp == 0,仍然有一些奇怪的事情:当significand == 0 你有+0 和-0。我不确定他们是否被认为是平等的。如果有人知道,请随时编辑帖子。但作为整数值,它们当然会有所不同。

      exp == 0significand != 0 发现非规范化数字时......虽然不相等,但将转换为不为 0 的最小数字中的 0。

      因此,如果您想要双射,请仅使用具有0 < exp < 255<正常 数,并避免使用 NaN、无限、0 和非正规数,因为这些情况 很奇怪。

      参考文献:

      【讨论】:

        【解决方案6】:
        f1 == f2
        

        不可能,请参阅this answer 了解更多信息。如果您确实想要近似相等性检查,则需要包含一个增量。

        【讨论】:

          猜你喜欢
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-30
          • 1970-01-01
          • 1970-01-01
          • 2010-12-19
          • 2011-01-04
          相关资源
          最近更新 更多