简体   繁体   中英

Java Unexpected Rounding of Double/Float

Can anyone explain the following behavior? This method is supposed to scale the loaded picture so that it is as large as it can be within certain bounds without going over.

private final File imageFile;
private final ImageLoaderListener listener;
private final int idealWidth;
private final int idealHeight;
private final float idealRatio;

@Override
protected BufferedImage doInBackground() throws Exception {
    BufferedImage origImage;
    BufferedImage scaledImage;
    int origHeight;
    int origWidth;
    float imgRatio;

    // Load the image.
    try {
        origImage = ImageIO.read( imageFile );
        origHeight = origImage.getHeight();
        origWidth = origImage.getWidth();
        imgRatio = origWidth / origHeight;
        //imgRatio = 5/7;
    } catch (Exception e){
        JOptionPane.showMessageDialog( AppFrame.getAppFrame(),
                "Could not load the image.", "Error Loading Image",
                JOptionPane.ERROR_MESSAGE );
        return null;
    }

    // Scale the image
    double scaleFactor = (imgRatio >= idealRatio) ? idealWidth/origWidth
                                                  : idealHeight/origHeight;
    int scaledWidth = (int) Math.floor( scaleFactor * origWidth );
    int scaledHeight = (int) Math.floor( scaleFactor * origHeight );

    scaledImage = new BufferedImage( scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB );
    AffineTransform at = new AffineTransform();
    at.scale(scaleFactor, scaleFactor);
    AffineTransformOp scaleOp = new AffineTransformOp( 
            at, AffineTransformOp.TYPE_BICUBIC );
    scaledImage = scaleOp.filter(origImage, scaledImage);

    return scaledImage;
}

This is the unexpected result: All of the division is rounding without my telling it to. So if I run this with idealWidth=1920 and idealHeight=925 , the debug variable list shows idealHeight = (float) 2.0 . Likewise, my test picture is 532x783, and imgRatio = (float) 0.0 . ScaleFactor is doing the same thing: the 532x783 image results in ScaleFactor = (double) 1.0

When I originally started to bugfix this, I had inadvertently declared the ratio variables ( idealRatio and imgRatio ) as int s. I saw this, changed them to doubles, and did a clean build, thinking it was fixed. Then I changed them to floats after doubles didn't work. Now I'm stumped. Why on earth would Java still be acting as if they were int s?

This is standard Java (and most statically typed languages, thanks Daniel) behavior. What you are doing here is integer division which will always return an integer (same type as values in division operation) unless you take measures to prevent it. You could either make the variables into floats/doubles or cast one to a float/double to have the division expression return a float/double with standard rounding.

Well, to start with, 5/7 is an integer expression.

(And so, apparently, are the other divisions, after a very brief review.)

FYI, you can't just assign the result to a double and have Java perform double precision division, you need to cast each of your integer terms to doubles as follows:

int x=4;
int y=19;
double z = (double)x/(double)y;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM