如何在Java中将双精度数舍入到最接近的奇数整数?

问题描述 投票:0回答:2

我想将

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 ...;
    }
}
java rounding
2个回答
2
投票

以下函数解决了本文末尾列出的所有测试用例。

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)

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

更新了答案以处理偶数,如评论中指出的那样。

© www.soinside.com 2019 - 2024. All rights reserved.