mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-19 01:47:52 +00:00
6430675: Math.round has surprising behavior for 0x1.fffffffffffffp-2
Reviewed-by: alanb
This commit is contained in:
parent
f4ec972481
commit
b4d4e3bed4
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -627,11 +627,9 @@ public final class Math {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest {@code int} to the argument. The
|
||||
* result is rounded to an integer by adding 1/2, taking the
|
||||
* floor of the result, and casting the result to type {@code int}.
|
||||
* In other words, the result is equal to the value of the expression:
|
||||
* <p>{@code (int)Math.floor(a + 0.5f)}
|
||||
* Returns the closest {@code int} to the argument, with ties
|
||||
* rounding up.
|
||||
*
|
||||
* <p>
|
||||
* Special cases:
|
||||
* <ul><li>If the argument is NaN, the result is 0.
|
||||
@ -649,17 +647,17 @@ public final class Math {
|
||||
* @see java.lang.Integer#MIN_VALUE
|
||||
*/
|
||||
public static int round(float a) {
|
||||
return (int)floor(a + 0.5f);
|
||||
if (a != 0x1.fffffep-2f) // greatest float value less than 0.5
|
||||
return (int)floor(a + 0.5f);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest {@code long} to the argument. The result
|
||||
* is rounded to an integer by adding 1/2, taking the floor of the
|
||||
* result, and casting the result to type {@code long}. In other
|
||||
* words, the result is equal to the value of the expression:
|
||||
* <p>{@code (long)Math.floor(a + 0.5d)}
|
||||
* <p>
|
||||
* Special cases:
|
||||
* Returns the closest {@code long} to the argument, with ties
|
||||
* rounding up.
|
||||
*
|
||||
* <p>Special cases:
|
||||
* <ul><li>If the argument is NaN, the result is 0.
|
||||
* <li>If the argument is negative infinity or any value less than or
|
||||
* equal to the value of {@code Long.MIN_VALUE}, the result is
|
||||
@ -676,7 +674,10 @@ public final class Math {
|
||||
* @see java.lang.Long#MIN_VALUE
|
||||
*/
|
||||
public static long round(double a) {
|
||||
return (long)floor(a + 0.5d);
|
||||
if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5
|
||||
return (long)floor(a + 0.5d);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static Random randomNumberGenerator;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -613,11 +613,8 @@ public final class StrictMath {
|
||||
public static native double pow(double a, double b);
|
||||
|
||||
/**
|
||||
* Returns the closest {@code int} to the argument. The
|
||||
* result is rounded to an integer by adding 1/2, taking the
|
||||
* floor of the result, and casting the result to type {@code int}.
|
||||
* In other words, the result is equal to the value of the expression:
|
||||
* <p>{@code (int)Math.floor(a + 0.5f)}
|
||||
* Returns the closest {@code int} to the argument, with ties
|
||||
* rounding up.
|
||||
*
|
||||
* <p>Special cases:
|
||||
* <ul><li>If the argument is NaN, the result is 0.
|
||||
@ -635,15 +632,12 @@ public final class StrictMath {
|
||||
* @see java.lang.Integer#MIN_VALUE
|
||||
*/
|
||||
public static int round(float a) {
|
||||
return (int)floor(a + 0.5f);
|
||||
return Math.round(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest {@code long} to the argument. The result
|
||||
* is rounded to an integer by adding 1/2, taking the floor of the
|
||||
* result, and casting the result to type {@code long}. In other
|
||||
* words, the result is equal to the value of the expression:
|
||||
* <p>{@code (long)Math.floor(a + 0.5d)}
|
||||
* Returns the closest {@code long} to the argument, with ties
|
||||
* rounding up.
|
||||
*
|
||||
* <p>Special cases:
|
||||
* <ul><li>If the argument is NaN, the result is 0.
|
||||
@ -662,7 +656,7 @@ public final class StrictMath {
|
||||
* @see java.lang.Long#MIN_VALUE
|
||||
*/
|
||||
public static long round(double a) {
|
||||
return (long)floor(a + 0.5d);
|
||||
return Math.round(a);
|
||||
}
|
||||
|
||||
private static Random randomNumberGenerator;
|
||||
|
||||
98
jdk/test/java/lang/Math/RoundTests.java
Normal file
98
jdk/test/java/lang/Math/RoundTests.java
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6430675
|
||||
* @summary Check for correct implementation of {Math, StrictMath}.round
|
||||
*/
|
||||
public class RoundTests {
|
||||
public static void main(String... args) {
|
||||
int failures = 0;
|
||||
|
||||
failures += testNearFloatHalfCases();
|
||||
failures += testNearDoubleHalfCases();
|
||||
|
||||
if (failures > 0) {
|
||||
System.err.println("Testing {Math, StrictMath}.round incurred "
|
||||
+ failures + " failures.");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static int testNearDoubleHalfCases() {
|
||||
int failures = 0;
|
||||
double [][] testCases = {
|
||||
{+0x1.fffffffffffffp-2, 0.0},
|
||||
{+0x1.0p-1, 1.0}, // +0.5
|
||||
{+0x1.0000000000001p-1, 1.0},
|
||||
|
||||
{-0x1.fffffffffffffp-2, 0.0},
|
||||
{-0x1.0p-1, 0.0}, // -0.5
|
||||
{-0x1.0000000000001p-1, -1.0},
|
||||
};
|
||||
|
||||
for(double[] testCase : testCases) {
|
||||
failures += testNearHalfCases(testCase[0], (long)testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testNearHalfCases(double input, double expected) {
|
||||
int failures = 0;
|
||||
|
||||
failures += Tests.test("Math.round", input, Math.round(input), expected);
|
||||
failures += Tests.test("StrictMath.round", input, StrictMath.round(input), expected);
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testNearFloatHalfCases() {
|
||||
int failures = 0;
|
||||
float [][] testCases = {
|
||||
{+0x1.fffffep-2f, 0.0f},
|
||||
{+0x1.0p-1f, 1.0f}, // +0.5
|
||||
{+0x1.000002p-1f, 1.0f},
|
||||
|
||||
{-0x1.fffffep-2f, 0.0f},
|
||||
{-0x1.0p-1f, 0.0f}, // -0.5
|
||||
{-0x1.000002p-1f, -1.0f},
|
||||
};
|
||||
|
||||
for(float[] testCase : testCases) {
|
||||
failures += testNearHalfCases(testCase[0], (int)testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testNearHalfCases(float input, float expected) {
|
||||
int failures = 0;
|
||||
|
||||
failures += Tests.test("Math.round", input, Math.round(input), expected);
|
||||
failures += Tests.test("StrictMath.round", input, StrictMath.round(input), expected);
|
||||
|
||||
return failures;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user