Math 函数
在线手册:中文 英文
PHP手册

abs

(PHP 4, PHP 5)

abs绝对值

说明

number abs ( mixed $number )

返回参数 number 的绝对值。如果参数 numberfloat,则返回的类型也是 float,否则返回 integer(因为 float 通常比 integer 有更大的取值范围)。

Example #1 abs()

<?php
$abs 
abs(-4.2); // $abs = 4.2; (double/float)
$abs2 abs(5);   // $abs2 = 5; (integer)
$abs3 abs(-5);  // $abs3 = 5; (integer)
?>

Math 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 绝对值

用户评论:

alex dot griffioen at gmail dot com (06-Jan-2012 02:45)

Easy way to toggle a bit using abs():

<?php
$flag
= 1; // either 0 or 1
$flag = abs($flag - 1);
?>

Tig (08-Oct-2011 11:23)

If doing a single conversion to ">= 0" on a random input, in order to workout the value of the input (corrected to 0 or greater), the quickest method is:

$x = abs($input);

After a bit more testing and thinking about how the test page (in the post below) works, it appears the results are correct, but _only_ when looping over the different methods for a lot of loops. For a single test or correction, the results are wrong.

The results for option 1 and 3 are very close to each other, but option 2 is clearly the quickest of the three.

After removing the loops, the results where:

1) Result [938]: 1.5974044799805E-5 sec.
2) Result [938]: 5.9604644775391E-6 sec.
3) Result [938]: 1.5020370483398E-5 sec.

(note the E-5 and E-6 at the end)

Tig (04-Oct-2011 01:13)

In trying to workout the fastest way to return a number equal to or great than 0 from any input, with < 0 turned positive as well, these are my results and how I tested:

Fastest method:
$x = floor($input);
$x = ($x < 0) ? ($x * -1) : $x;

With ?n=987 passed
1) Result [987]: 0.020493030548096 sec.
2) Result [987]: 0.072222948074341 sec.
3) Result [987]: 0.23027300834656 sec.

With ?n=-821
1) Result [821]: 0.023087024688721 sec.
2) Result [821]: 0.073657035827637 sec.
3) Result [821]: 0.24681091308594 sec.

With ?n=foo
1) Result [0]: 0.020076990127563 sec.
2) Result [0]: 0.065827131271362 sec.
3) Result [0]: 0.17472290992737 sec.

Also works with nothing passed.

The test page code:
<?php

   
// test 1
   
$start = microtime(true);
   
$x = floor($_GET['n']);
   
$i = 0;
    do {
       
$tmp = ($x < 0) ? ($x * -1) : $x;
    } while(
$i++ < 100000);
   
$end = microtime(true);
    echo
'1) Result ['.$tmp.']: '.($end - $start).' sec.<br />';

   
// test 2
   
$start = microtime(true);
   
$x = $_GET['n'];
   
$i = 0;
    do {
       
$tmp = abs($x);
    } while(
$i++ < 100000);
   
$end = microtime(true);
    echo
'2) Result ['.$tmp.']: '.($end - $start).' sec.<br />';

   
// test 3
   
$start = microtime(true);
   
$x = floor($_GET['n']);
   
$i = 0;
    do {
       
$tmp = str_replace('-','',$x);
    } while(
$i++ < 100000);
   
$end = microtime(true);
    echo
'3) Result ['.$tmp.']: '.($end - $start).' sec.<br />';

?>

svein dot tjonndal at gmail dot com (25-May-2011 08:44)

If you don't have/want GMP and are working with large numbers/currencies:

<?php
function mb_abs($number)
{
  return
str_replace('-','',$number);
}
?>

No need to worry about encoding, as your numbers should all be basic (ANSI) strings.

lkj dot korn at gmail dot com (02-Aug-2008 05:58)

[EDIT by danbrown AT php DOT net: Merged two posts by the same author.]

This is a note to concordia's comment at http://us.php.net/manual/en/function.abs.php#58508
I believe there is an easier way to turn a positive number into a negative one and vice versa in one line:
<?php
function change_pol($integer){
    return (
0 - $integer);
}
?>

It takes another additional line to check if it's really a number:
<?php
function change_pol($integer){
    if(!
is_numeric($integer)){ return false; }
    return (
0 - $integer);
}
?>
Keep in mind that if I do 0 - -5 (given that $integer is -5), it will turn into +, thus turning the result into +5. Works like a charm for me. Input like '-5' will work as well (as PHP turns strings automatically into an integer or float), even '-.9' will return as 0.9.

Another thing I'd like to note is that the variable name $integer used in my examples aren't really advised as the function goes beyond simple integers. Initially, I used this function only for the handling of integers, hence the variable name. It is only later that I've discovered it goes beyond integers. 0 will also return to 0 (if that shouldn't be obvious).

Perhaps it is better to make it return NULL instead of FALSE when it fails the is_numeric condition, so that there's no mix with the function's result to be false instead of actually 0, however only checking with '===' instead of '==' should solve this, I believe.

Ister (17-Jul-2008 09:59)

[*EDIT* by danbrown AT php DOT net: Merged user's corrected code with previous post content.]


jeremys indicated one thing - there is no sgn function wich actually seems a bit strange for me. Of course it is as simple as possible, but it is usefull and it is a standard math function needed occasionally.

Well, I have solved this function in a bit different matter:

<?php

function sgn($liczba)
{
    if(
$liczba>0)
       
$liczba=1;
    else if(
$liczba<0)
       
$liczba=-1;
    else if(!
is_numeric($liczba))
       
$liczba=null;
    else
       
$liczba=0;
    return
$liczba;
}

?>

The difference is that it returns null when the argument isn't a number at all.

zyphos at zyphos dot be (18-Jun-2008 09:15)

I think there are faster methods for doing an on/off.

$value = (1 - $value);

or better:

$value = (1 ^ $value); // which uses the xor function.

Below are the benchs on my computer, for loop of 10,000,000 with PHP Version 5.2.1

$value = abs($value -1); // 4.12641406059 sec
$value = (1 - $value); // 1.58847904205 sec
$value =  (1 ^ $value); // 1.49518704414 sec

Note that using function call for such operation is very slow.
function on_off($value) {
 return (1 ^ $value);
} // 7.10739612579 sec

olivierlabbe at votreespace dot net (11-Jun-2008 07:35)

making an on/off switch with 0 and 1

function on_off($value) {
 return abs($value -1);
}

if you send 0, it'll return 1, and 1 return 0.

0 - 1 = -1, absolute of -1 = 1
1 - 1 = 0, absolute of 0 = 0

estoesunapija at hotmail dot com (26-Mar-2008 10:29)

//Not for working with float
//anyways, seems cool for integers
//This works, iff is_int($num)

function nabs ($num=NULL){
   $num = (int)$num;
   if ($num<=0) return 0; //why bother bit flipping with 0
   return ~$num + 1;
}

thomas at tgohome dot com (29-Dec-2007 11:00)

If we want to into a war about speed with negative absolute numbers, I think bitwise operations should just about do it.

<?php
function n_abs($v) { return ~abs($v) + 1; }
?>

A NOT operation on any number with a sign bit will produce the negative of that number minus one. All we need to do is add one. Voila!

Speed test results (30000 iterations of various methods) produced very close dueling between the previous suggested method. Although I am on an overloaded Windows PC so I'm no benchmark, and I'll leave it up to you, the reader of this message.

Josh (08-Jan-2006 12:06)

Let's say you are resizing images to a standard size that can be expressed as a ratio (width/height). The problem I came into was that I wanted to be reasonable with the proportion of the images that my customer is uploading (couldn't we all use a little less horizontal on pictures?), but I wanted to reject the horizontal pictures when they were uploading vertical ones. So I wanted to accept proportions of images that were within a reasonable threshold (+ or -) of what I will be resizing them to.

Assuming a standard of 1 to 4 (0.25) and a threshold of no more than 0.05 deviation, then the number 0.30 and 0.20 would return true and 0.19 would return false.

<?php

function threshold($given,$thresh,$standard)
{
     return (
abs($given-$standard)<=$thresh) ? true : false;
}

?>

jeremys at hang dash wire dot com (12-Dec-2005 04:05)

I'm unable to replicate concordia's problem with the $n = $n - $n * 2 code.  I agree with the simplification to $n *= -1.  But there's no reason that concordia's code should return 6 for the value -2, and it doesn't appear to.  When I tried it, PHP returned 2, as it should.  If PHP were somehow flipping the sign of integers randomly, that would be a *major* bug!

There doesn't seem to be a sgn() function yet.  Here's some quick code to do it:

function sgn($x) {
   return $x ? ($x>0 ? 1 : -1) : 0;
}

You could use $x ? abs($x)/$x : 0 too, but might as well avoid the float division.

Lazarus (12-Dec-2005 02:53)

Even that is unnecessarily complex. Try this:

<?php

function n_abs($v) { return -abs($v) ; }

?>

Faster too.

rdk (10-Nov-2005 07:04)

concordia, you seem to be overcomplicating matters.  If you want to do the reverse of the abs function, the only code required is:

<?php

function n_abs($num) {
    return (
$num > 0) ? $num * -1 : $num;
}

n_abs(2); //-2
n_abs(-2); //-2

?>

If you want to switch the sign bit of a number, as your example seems to indicate...
turn_neg (2); // -2
turn_neg (-2); // 2
...you just need to do $num *= -1;

Your function also doesn't seem to work. Switching "if (is_neg ($num))" to "if (!is_neg ($num))" would make it function as indicated by your comments (i.e. toggle the sign bit), but it would still be overly complicated.

alreece45 at yahoo dot com (10-Aug-2005 08:05)

Both of the below codes were wrong.

<?php

// Check to see if $range is numberic, if not, set it to the integer value 1

if(!is_numeric($range)) {

 
$range=1;

}

// Check to see if $range is an integer and not a float. Use is_int() and not int().

if(!is_int($range)) {

// Make it an integer. Use intval() here, not int_val.

 
$range=intval($range);

}

$range=abs($range);

?>

The only thing I don't get is why we have to check before doing the functions. Whether or not we do the functions it will give us what we want. The only check I really understand being there is the one that sets it to one.

Why not just do:

<?php

// If $range is numberic, make it in positive integer, otherwise, make it one.

$range = is_numeric($range) ? abs(intval($range)) : 1;

?>

Seems like a lot less code. Or If you prefer to stay with if statements:

<?php

if(is_numberic($range)) {

 
// If $range is numberic, make it in positive integer.

 
$range = abs(intval($range));

}

else {

 
//otherwise, make it one.

 
$range = 1;

}

?>

Both ways seem smaller to me.

abodeman at y a h o o (25-May-2004 01:59)

There's another problem in the below code. The correct function to see whether a value is an integer is is_int(), not int(), so the code should look like this:

<?php
if(!is_numeric($range))//checks for numeric input
{
$range=1;
}
//sets $range to integer 1 if input is anything other than a numeric value
if(!is_int($range))//checks to make sure it is an integer (not decimal)
{
$range=int_val($range);
}
//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>

mbender at duforu dot com (01-Mar-2004 09:59)

In reference to the previous code sample the int_val function is actually intval() [http://us4.php.net/manual/en/function.intval.php]:

<?php
if(!is_numeric($range))//checks for numeric input
 
{
 
$range=1;
 }
//sets $range to integer 1 if input is anything other than a numeric value
if(!int($range))//checks to make sure it is an integer (not decimal)
 
{
 
$range=intval($range) // not ->  int_val($range);
 
}//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>

bgustin AT trukfixer DOT com (16-Jul-2003 04:50)

assume we take user input from a form untreated and assign it to variable $range. We want to be sure this number is a Positive Whole number, since abs() just sets a number to positive or 0, and we dont want decimals...

<?php
if(!is_numeric($range))//checks for numeric input
{
$range=1;
}
//sets $range to integer 1 if input is anything other than a numeric value
if(!int($range))//checks to make sure it is an integer (not decimal)
{
$range=int_val($range);
}
//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>

for example the input "testing" would return $range =1,
the input "3.578" would return value=3
If the input is null, I am havent tested to see if it gets set to 1 courtesy of int_val or not, but I believe it will be.

I'm sure there's probably a more elegant way to do this using regex, however for an apprentice php coder, this might be a little easier to understand and use.