Java 整数四舍五入(与除法相关)

4

我在整数除法上遇到了一个意外,它没有像预期的那样向下取整。

简单的代码:

public class HelloMath {

    public static void main(String[] args) {
        for (int s=1; s< 20; s++)
        {
            int div = 1<<s;
            int res = (int) ((float)-8/ s);
            System.out.printf("Bit %d, result %d\n", s, res);
        }
    }

}

即使使用了显式的(float)转换,输出结果仍然是:
Bit 1, result -8
Bit 2, result -4
Bit 3, result -2
Bit 4, result -2
Bit 5, result -1
Bit 6, result -1
Bit 7, result -1
Bit 8, result -1
Bit 9, result 0
Bit 10, result 0
Bit 11, result 0
Bit 12, result 0
Bit 13, result 0
Bit 14, result 0
Bit 15, result 0
Bit 16, result 0
Bit 17, result 0
Bit 18, result 0
Bit 19, result 0

我原本期望一直得到-1。
真正出现这种情况的代码如下:
public static int fluidTo8th(int fluid)
{
    if (0 == fluid)
        return 0;   // Technically, this isn't needed :-).
    int wholePart = (fluid-1) * 8 / RealisticFluids.MAX_FLUID; // -1 gets rounding correct;
    // consider fluid of exactly 1/8th.
    return 1+wholePart;
}

RealisticFluids.MAX_FLUID的值为(1<<20)。

代码应该接受一个输入,该输入介于1和MAX_FLUID之间(如果输入块是空气,则为0),并返回从0到7的数字--从1到1/8最大值为0,从1/8+1到2/8为2,一直到7/8+1到8/8为7。

我期望整数运算将所有分数向下舍入。但事实并非如此--我得到了很多错误,因为5.999变成了6而不是5。

  1. 这种行为在哪里有记录?
  2. 最简单的解决方法是什么,以获得我期望的向下舍入?

(完整的代码上下文:https://github.com/keybounce/Finite-Fluids/blob/master/src/main/java/com/mcfht/realisticfluids/Util.java


如果你实际上是通过div而不是s进行除法,结果可能会有所不同。我的意思是,我认为你创建div是有原因的。 - Andreas
s = 1时,将-8除以s得到-8,将-8除以div(1<<1=2)得到-4,那么你为什么期望它是-1呢?--- 当s = 9时,将-8除以s得到0(从-0.8888889四舍五入),将-8除以div(1<<9=512)得到0(从-0.015625四舍五入),那么你为什么期望它是-1呢? - Andreas
1个回答

2
我期望整数运算会把所有小数都向下取整。首先,你并没有进行整数除法:你正在做浮点数除法。 (float)-8 是一个浮点表达式。因此,在发生除法之前,(float)-8/s 中的 s 会被提升为(float)。接着,浮点结果会被转换为整型。Reusman 说整数除法向零舍入。好吧,float->int 转换也向零舍入。

2
Java规范支持您的说法:JLS §5.1.3 *...浮点值将被四舍五入为整数值V,使用IEEE 754向零舍入模式进行舍入(§4.2.3)*。 - Andreas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接