有没有办法在不使用 java 中的 Math.abs() 方法的情况下找到数字的绝对值。
10 回答
如果您查看 Math.abs 内部,您可能会找到最佳答案:
例如,对于花车:
/*
* Returns the absolute value of a {@code float} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
* Special cases:
* <ul><li>If the argument is positive zero or negative zero, the
* result is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
* In other words, the result is the same as the value of the expression:
* <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
*/
public static float abs(float a) {
return (a <= 0.0F) ? 0.0F - a : a;
}
是的:
abs_number = (number < 0) ? -number : number;
对于整数,这很好用(除了Integer.MIN_VALUE
,其绝对值不能表示为int
)。
对于浮点数,事情就更微妙了。例如,此方法——以及迄今为止发布的所有其他方法——将无法正确处理负零。
为了避免自己处理这些微妙之处,我的建议是坚持使用Math.abs()
.
像这样:
if (number < 0) {
number *= -1;
}
由于 Java 是一种静态类型的语言,我希望采用 int 的 abs 方法返回一个 int,如果它期望一个 float 返回一个 float,对于一个 Double,返回一个 Double。也许它可以总是为双打和双打等返回装箱或未装箱的类型。
因此,每种类型都需要一个方法,但现在出现了一个新问题:对于 byte、short、int、long,负值的范围比正值的范围大 1。
那么该方法应该返回什么
byte abs (byte in) {
// @todo
}
如果用户在 -128 上调用 abs?您总是可以返回下一个更大的类型,以保证范围适合所有可能的输入值。这将长期导致问题,其中不存在正常的更大类型,并使用户在测试后总是降低值 - 可能很麻烦。
第二个选项是抛出一个算术异常。这将防止在已知输入受限的情况下强制转换和检查返回类型,这样 X.MIN_VALUE 就不会发生。想想 MONTH,表示为 int。
byte abs (byte in) throws ArithmeticException {
if (in == Byte.MIN_VALUE) throw new ArithmeticException ("abs called on Byte.MIN_VALUE");
return (in < 0) ? (byte) -in : in;
}
“让我们忽略 MIN_VALUE 的罕见情况”的习惯不是一种选择。首先使代码工作 - 然后使其快速。如果用户需要一个更快但有问题的解决方案,他应该自己编写。可能可行的最简单的解决方案意味着:简单,但不要太简单。
由于代码不依赖于状态,该方法可以而且应该是静态的。这允许快速测试:
public static void main (String args []) {
System.out.println (abs(new Byte ( "7")));
System.out.println (abs(new Byte ("-7")));
System.out.println (abs((byte) 7));
System.out.println (abs((byte) -7));
System.out.println (abs(new Byte ( "127")));
try
{
System.out.println (abs(new Byte ("-128")));
}
catch (ArithmeticException ae)
{
System.out.println ("Integer: " + Math.abs (new Integer ("-128")));
}
System.out.println (abs((byte) 127));
System.out.println (abs((byte) -128));
}
我捕获了第一个异常并让它运行到第二个,只是为了演示。
编程中有一个坏习惯,那就是程序员更关心快速而不是正确的代码。太遗憾了!
如果你好奇为什么负值比正值多一个,我有一张图表给你。
虽然这不应该是一个瓶颈,因为现代处理器上的分支问题通常不是问题,但对于整数,您可以使用此处概述的无分支解决方案:http: //graphics.stanford.edu /~seander/bithacks.html#IntegerAbs。
(x + (x >> 31)) ^ (x >> 31);
但是,在明显的 Integer.MIN_VALUE 情况下,这确实会失败,因此这是一种使用风险自负的解决方案。
如果整数 x 的绝对值不使用 Math.abs()、条件或按位运算,以下可能是 Java 中的一种可能解决方案。
(int)(((long)x*x - 1)%(double)x + 1);
因为 Java 将a%b
视为a - a/b * b
,所以无论“b”是什么符号,结果的符号都将与“a”相同;(x*x-1)%x
将等于abs(x)-1
;“long”的类型转换是为了防止溢出并double
允许除以零。
同样,x = Integer.MIN_VALUE
由于减 1 会导致溢出。
您可以使用 :
abs_num = (num < 0) ? -num : num;
这是一个返回数字绝对值的单行解决方案:
abs_number = (num < 0) ? -num : num;
-num 将等于 Integer.MIN_VALUE 的 num 为
Integer.MIN_VALUE = Integer.MIN_VALUE * -1
使用数学类
Math.abs(num);