简体   繁体   English

在不使用Math.abs()的情况下查找数字的绝对值

[英]Finding absolute value of a number without using Math.abs()

有没有办法在不使用java中的Math.abs()方法的情况下找到数字的绝对值。

If you look inside Math.abs you can probably find the best answer: 如果您查看Math.abs,您可能会找到最佳答案:

Eg, for floats: 例如,对于花车:

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

Yes: 是:

abs_number = (number < 0) ? -number : number;

For integers, this works fine (except for Integer.MIN_VALUE , whose absolute value cannot be represented as an int ). 对于整数,这很好(除了Integer.MIN_VALUE ,其绝对值不能表示为int )。

For floating-point numbers, things are more subtle. 对于浮点数,事情更加微妙。 For example, this method -- and all other methods posted thus far -- won't handle the negative zero correctly. 例如,此方法 - 以及到目前为止发布的所有其他方法 - 将无法正确处理负零

To avoid having to deal with such subtleties yourself, my advice would be to stick to Math.abs() . 为了避免不得不自己处理这些细微之处,我的建议是坚持使用Math.abs()

Like this: 像这样:

if (number < 0) {
    number *= -1;
}

Since Java is a statically typed language, I would expect that a abs-method which takes an int returns an int, if it expects a float returns a float, for a Double, return a Double. 由于Java是一种静态类型语言,我希望一个带有int的abs方法返回一个int,如果它期望一个float返回一个浮点数,对于一个Double,返回一个Double。 Maybe it could return always the boxed or unboxed type for doubles and Doubles and so on. 也许它总是可以返回双打和双打的盒装或非盒装类型等等。

So you need one method per type, but now you have a new problem: For byte, short, int, long the range for negative values is 1 bigger than for positive values. 所以每种类型需要一个方法,但现在你遇到了一个新问题:对于byte,short,int,long,负值的范围比正值大1。

So what should be returned for the method 那么应该为该方法返回什么

byte abs (byte in) {
   // @todo
}

If the user calls abs on -128? 如果用户在-128上调用abs? You could always return the next bigger type so that the range is guaranteed to fit to all possible input values. 您可以随时返回下一个更大的类型,以确保范围适合所有可能的输入值。 This will lead to problems for long, where no normal bigger type exists, and make the user always cast the value down after testing - maybe a hassle. 这将导致长时间存在的问题,其中不存在正常的较大类型,并且使用户在测试后总是将值降低 - 可能是麻烦。

The second option is to throw an arithmetic exception. 第二种选择是抛出算术异常。 This will prevent casting and checking the return type for situations where the input is known to be limited, such that X.MIN_VALUE can't happen. 这将阻止在已知输入受限的情况下转换和检查返回类型,从而不会发生X.MIN_VALUE。 Think of MONTH, represented as int. 想想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; 
}

The "let's ignore the rare cases of MIN_VALUE" habit is not an option. “让我们忽略罕见的MIN_VALUE案例”习惯不是一种选择。 First make the code work - then make it fast. 首先使代码工作 - 然后快速。 If the user needs a faster, but buggy solution, he should write it himself. 如果用户需要更快但有缺陷的解决方案,他应该自己编写。 The simplest solution that might work means: simple, but not too simple. 最简单的解决方案可能有效:简单但不太简单。

Since the code doesn't rely on state, the method can and should be made static. 由于代码不依赖于状态,因此该方法可以而且应该是静态的。 This allows for a quick test: 这允许快速测试:

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

I catch the first exception and let it run into the second, just for demonstration. 我抓住第一个例外,让它进入第二个例子,仅用于演示。

There is a bad habit in programming, which is that programmers care much more for fast than for correct code. 编程中存在一个坏习惯,即程序员对正确代码的关注要快得多。 What a pity! 太遗憾了!


If you're curious why there is one more negative than positive value, I have a diagram for you . 如果你很好奇为什么还有一个负值而不是正值,我会给你一个图表

Although this shouldn't be a bottle neck as branching issues on modern processors isn't normally a problem, but in the case of integers you could go for a branch-less solution as outlined here: http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs . 虽然这不应该是瓶颈,因为现代处理器上的分支问题通常不是问题,但在整数的情况下,你可以选择这里概述的无分支解决方案: http//graphics.stanford.edu /~seander/bithacks.html#IntegerAbs

(x + (x >> 31)) ^ (x >> 31);

This does fail in the obvious case of Integer.MIN_VALUE however, so this is a use at your own risk solution. 但是,在Integer.MIN_VALUE的明显情况下,这确实失败了,因此这是一个自行风险解决方案。

使用Math类

Math.abs(num);

您可以使用 :

abs_num = (num < 0) ? -num : num;

这是一个单行解决方案,它将返回一个数字的绝对值:

abs_number = (num < 0) ? -num : num;

对于Integer.MIN_VALUE,-num将等于num

 Integer.MIN_VALUE =  Integer.MIN_VALUE * -1

In case of the absolute value of an integer x without using Math.abs(), conditions or bit-wise operations, below could be a possible solution in Java. 如果不使用Math.abs(),条件或按位运算的整数x的绝对值,下面可能是Java中的可能解决方案。

(int)(((long)x*x - 1)%(double)x + 1);

Because Java treats a%b as a - a/b * b , the sign of the result will be same as "a" no matter what sign of "b" is; 因为Java将a%b视为-a a - a/b * b ,所以无论“b”的符号是什么,结果的符号都将与“a”相同; (x*x-1)%x will equal abs(x)-1 ; (x*x-1)%x等于abs(x)-1 ; type casting of "long" is to prevent overflow and double allows dividing by zero. “long”的类型转换是为了防止溢出和double允许除以零。

Again, x = Integer.MIN_VALUE will cause overflow due to subtracting 1. 同样, x = Integer.MIN_VALUE会因减1而导致溢出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM