Java неожиданное округление двойного / плавающего - PullRequest
1 голос
/ 09 сентября 2011

Может кто-нибудь объяснить следующее поведение? Предполагается, что этот метод позволяет масштабировать загруженное изображение так, чтобы оно было настолько большим, насколько это может быть в определенных пределах, без перехода.

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;
}

Это неожиданный результат: все дивизии округляются, а я об этом не говорю. Так что, если я запустлю это с idealWidth=1920 и idealHeight=925, список переменных отладки покажет idealHeight = (float) 2.0. Аналогично, моя тестовая картинка 532x783 и imgRatio = (float) 0.0. ScaleFactor делает то же самое: изображение 532x783 дает ScaleFactor = (double) 1.0

Когда я изначально начал исправлять это, я случайно объявил переменные отношения (idealRatio и imgRatio) как int s. Я увидел это, изменил их на двойные и сделал чистую сборку, думая, что это исправлено. Затем я изменил их на поплавки после того, как двойники не работали Теперь я в тупике. С какой стати Java все еще будет вести себя так, как если бы они были int с?

Ответы [ 3 ]

5 голосов
/ 09 сентября 2011

Это стандартное поведение Java (и большинства статически типизированных языков, спасибо Дэниелу).Здесь вы выполняете целочисленное деление, которое всегда будет возвращать целое число (того же типа, что и значения в операции деления), если только вы не примете меры для его предотвращения.Вы можете либо преобразовать переменные в числа с плавающей точкой / двойники, либо преобразовать их в число с плавающей точкой / двойные числа, чтобы выражение деления возвращало число с плавающей точкой или двойное число со стандартным округлением.

3 голосов
/ 09 сентября 2011

Ну, для начала, 5/7 является целочисленным выражением.

(И, очевидно, таковы другие подразделения после очень краткого обзора.)

1 голос
/ 09 сентября 2011

К вашему сведению, вы не можете просто присвоить результат удвоению, и чтобы Java выполняла деление с двойной точностью, вам нужно привести каждое ваше целочисленное слагаемое к удвоенным значениям следующим образом:

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