【问题标题】:Is it possible to perform bit operations on a float in Java?是否可以在 Java 中对浮点数执行位操作?
【发布时间】:2016-09-26 07:52:27
【问题描述】:

我有一些 C 代码,我正在通过大量位级操作将其转换为 java。

我有以下代码:

float test(float uf) {
    return uf ^ (1 << 31);
}

在原始 C 代码中,uf 是一个无符号值。由于 java 没有无符号值,我将 uf 更改为浮点数。现在,我收到一个错误,说第一个类型是浮点数,第二个是整数。

我知道有它的库,但我只是想使用位操作只是为了看看我可以出于好奇使用位操作对 Java 做什么。

那么,我的第一个问题是,是否可以在不使用库的情况下使用 Java 执行上述操作?其次,有什么理由不应该在 java 中工作(除了有库可以为你做这件事之外)?

【问题讨论】:

  • 您当然可以实现自己的“浮点位移”,但there is no built-in bitshift on non-integral primitives in Java。至于你的第二个问题:非整数类型的位移对人类来说比整数类型更难解释。因此,可以提出这样的论点,即这种操作会降低代码的可理解性。
  • 您已经破坏了您的代码:任意 32 位值(您的典型无符号值)不完全适合只有 24 位尾数的 32 位浮点数。会有截断。所以将 unsigned 转换为 float 是行不通的。您也许可以尝试双打……但我怀疑您的想法已被打破,您应该尝试其他方法。如果您正在在 C 中使用 32 位整数,那么在 Java 中尝试使用 64 位长。
  • 你可以用 int 模拟 uint 就好了。你不能用float模拟uint。
  • 如果你真的想操作float 的位,你可以使用Float.floatToIntBits(float)。但这听起来并不是你想要做的。
  • @Sam 是的,我正在尝试仅使用位操作。

标签: java floating-point bit-manipulation


【解决方案1】:

没有。我们不能对浮点数进行位移。

该操作只是翻转第 31 位(从第零位开始)。你可以在java中做到这一点。

int test(int uf) {
    return uf ^ (1 << 31);
}

这就是你的功能。您遇到的问题不是设置该位,而是知道如果该数字为负数,则它实际上是一个大于该数字的数字 0xBFFFFFFF。只要您始终将 int 视为 32 位序列,而不是在适当的时候检查它的值,就可以了。


如果你想要 32 位来给你一个合适的数字。使用长。

long test(int uf) {
    return (uf & 0x00000000ffffffffL) ^ (1 << 31);
}

然后您可以在比较中正确使用它,如果您需要它作为 int,只需将其转换为 int。如果我们将 unsigned 转换为其他类型,这比浮点数要好得多。


答案 2:我们当然应该在 java 中使用位操作,因为它们在 java 中非常快。通常在关键任务代码中,最好在关键点转换为它们,直到只使用原语,甚至是本机编译代码。

【讨论】:

  • 题主特意询问floats上的位操作。因此,这个答案完全错过了第一个问题。第二个问题没有回答。
  • FWIW 你可以很容易地翻转一个浮动的标志.. 并不是说​​它会帮助一般的 OP
  • @Turing85 专业提示:这与uf ^ (1 &lt;&lt; 31) 完全不同
  • 好吧,但是有一个浮动并不能解决 OPs 问题,只能解决他的奇怪尝试
  • @JustBlossom 这个问题很好,但这是一个经典的 XY 问题,您选择解决问题的方式不起作用。即使我们解决了您当前的问题(即只是否定浮动),您也会遇到越来越多的麻烦,其中一些非常困难(指数问题),还有一些最终无法解决(NaN)。
【解决方案2】:

Java 中的非整数类型不允许按位运算。请参阅此参考: http://cs-fundamentals.com/java-programming/java-bitwise-operators.php.

就“不在位级别工作”的任何理由而言。答案是不。在 Java 中进行按位运算有很多正当理由。示例包括 JavaCard 应用程序、处理低级网络协议等。

【讨论】:

    【解决方案3】:

    正如其他答案所说,Java 中的浮点值没有按位运算。但是,您问题的这一部分清楚地表明这是 XY 问题的一个实例:您正在寻找 Y 的解决方案,而您实际上想要解决 X,因为您认为 Y 是最好的解决方案,但现在您被卡住了。

    在原始 C 代码中,uf 是一个无符号值。由于 java 没有无符号值,我将 uf 更改为浮点数。现在,我收到一个错误,说第一个类型是浮点数,第二个是整数。

    为什么不能使用长整数或普通整数?确实,常见的 Java 算术运算将 int 值视为有符号,但 methods in java.lang.Integer 对两个 int 值进行运算时将它们视为无符号。

    那么,你会在 C 中的什么地方这样做:

    unsigned int fun(unsigned int a, unsigned int b) {
        unsigned int x;
        scanf("%u", &x);
        return a * x + b/2u;
    }
    

    在 Java 中,您可以这样做(注意,当使用 2-补码表示时,加法和乘法对于有符号或无符号整数都是相同的操作):

    int fun(int a, int b) {
        // You need to get the value as a string first, there is no nextUnsignedInt in Scanner
        int x = Integer.parseUnsignedInt(new java.util.Scanner(System.in).next());
        return a*x + Integer.divideUnsigned(b, 2);
    }
    

    【讨论】:

    • 即使乘法对于有符号和无符号也是一样的,这就是为什么 multiplyUnsigned 不是一个东西。
    【解决方案4】:

    虽然您不能直接将位操作应用于浮点数,但可以将浮点数转换为具有相同位表示的整数(澄清:位将相等,数值不会)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-01
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多