我想将
double
舍入到 Java 中最接近的奇数数学整数 (long
)。这是一个测试程序:
public class RoundToOdd {
public static void main(String[] args) {
System.out.println(roundToOdd(2.1)); // expected: 3
System.out.println(roundToOdd(4.9)); // expected: 5
System.out.println(roundToOdd(3.7)); // expected: 3
System.out.println(roundToOdd(1.1)); // expected: 1
System.out.println(roundToOdd(7.0)); // expected: 7
System.out.println(roundToOdd(2.0)); // expected: 1 or 3, depends on requirements
}
public static long roundToOdd(double d) {
return ...;
}
}
以下函数解决了本文末尾列出的所有测试用例。
public static long roundToOdd(double d) {
if (d > Long.MAX_VALUE) {
return Long.MAX_VALUE;
} else if (d <= Long.MIN_VALUE) {
return Long.MIN_VALUE + 1;
}
return Math.round((d + 1.0) / 2.0) * 2 - 1;
}
这个函数最重要的部分是公式
Math.round((d + 1.0) / 2.0) * 2 - 1
,它计算所有有限数d
和的结果
Long.MIN_VALUE < d <= Long.MAX_VALUE
或 d
为 NaN
(不是数字)。
Math.round((d + 1.0) / 2.0) * 2 - 1
首先将数字 d
转换为更高的 (d + 1.0)
,然后按顺序执行步骤 /2、四舍五入到整数和 *2,四舍五入到偶数。这个结果高了1,因为我们在四舍五入之前加了1,所以最后我们必须做-1
才能达到正确的奇数。d
是 NaN
,则结果是 -1
,因为 Math.round(Double.NaN)
会导致 0
。
if
对特殊情况的测试,即所有值高于Long.MAX_VALUE
或低于或等于Long.MIN_VALUE
(包括+Infinity
/ -Infinity
)。这些都是特殊情况,因为无论 d
低于 Long.MIN_VALUE
多远,与 long
最接近的奇数 d
值就是 Long.MIN_VALUE + 1
,或者无论 d
高于 Long.MAX_VALUE
多远,收盘奇数 long
值为 Long.MAX_VALUE
。
测试用例:
-Infinity -> -9223372036854775807 ✔️ (expected -9223372036854775807)
-9223372036854775808.0 -> -9223372036854775807 ✔️ (expected -9223372036854775807)
-1152921504606846976.0 -> -1152921504606846977 ✔️ (expected one of [-1152921504606846977, -1152921504606846975])
-9007199254740994.0 -> -9007199254740993 ✔️ (expected one of [-9007199254740995, -9007199254740993])
-9007199254740992.0 -> -9007199254740991 ✔️ (expected one of [-9007199254740993, -9007199254740991])
-7.0 -> -7 ✔️ (expected -7)
-4.9 -> -5 ✔️ (expected -5)
-3.7 -> -3 ✔️ (expected -3)
-2.1 -> -3 ✔️ (expected -3)
-2.0 -> -1 ✔️ (expected one of [-1, -3])
-1.1 -> -1 ✔️ (expected -1)
-0.1 -> -1 ✔️ (expected -1)
0.0 -> 1 ✔️ (expected one of [-1, 1])
0.1 -> 1 ✔️ (expected 1)
1.1 -> 1 ✔️ (expected 1)
2.0 -> 3 ✔️ (expected one of [1, 3])
2.1 -> 3 ✔️ (expected 3)
3.7 -> 3 ✔️ (expected 3)
4.9 -> 5 ✔️ (expected 5)
7.0 -> 7 ✔️ (expected 7)
9007199254740992.0 -> 9007199254740991 ✔️ (expected one of [9007199254740991, 9007199254740993])
9007199254740994.0 -> 9007199254740995 ✔️ (expected one of [9007199254740993, 9007199254740995])
1152921504606846976.0 -> 1152921504606846975 ✔️ (expected one of [1152921504606846975, 1152921504606846977])
9223372036854775808.0 -> 9223372036854775807 ✔️ (expected 9223372036854775807)
Infinity -> 9223372036854775807 ✔️ (expected 9223372036854775807)
NaN -> -1 ✔️ (expected -1)
这应该可以做到:
public class RoundToOdd {
public static void main(String[] args) {
System.out.println(roundToOdd(2.1)); // expected: 3
System.out.println(roundToOdd(4.9)); // expected: 5
System.out.println(roundToOdd(3.7)); // expected: 3
System.out.println(roundToOdd(1.1)); // expected: 1
System.out.println(roundToOdd(2.0));
System.out.println(roundToOdd(1.0));
}
public static long roundToOdd(double d) {
long value = 1l;
if(Math.floor(d) % 2 == 0) {
if(d % 2 != 0) {
value = (long) Math.ceil(d);
} else if (d > Long.MAX_VALUE) {
value = Long.MAX_VALUE;
} else {
value = (long) d - 1;
}
} else {
value = (long) Math.floor(d);
}
return value;
}
}
更新了答案以处理偶数,如评论中指出的那样。