18

I know of the PHP function floor() but that doesn't work how I want it to in negative numbers.

This is how floor works

floor( 1234.567); //  1234
floor(-1234.567); // -1235

This is what I WANT

truncate( 1234.567); //  1234
truncate(-1234.567); // -1234

Is there a PHP function that will return -1234?

I know I could do this but I'm hoping for a single built-in function

$num = -1234.567;
echo $num >= 0 ? floor($num) : ceil($num);
chrislondon
  • 12,487
  • 5
  • 26
  • 65
  • I don't think there is one... why bother about that few characters? The intention of your line is quite clear. – Yogu Jun 29 '13 at 19:11
  • 3
    `number_format($num, 0, '', '');`? – Ohgodwhy Jun 29 '13 at 19:11
  • @Ohgodwhy I just tried the number_format way and it actually returns -1235 like the `floor()` function does. Strange! – chrislondon Jun 29 '13 at 19:15
  • Why do you want to avoid the single-line solution you mentioned? Of course, you could wrap that into a function if that were your goal, but testing for whether floor or ceiling is the correct operation based on sign is the appropriate approach based on PHP's definition of available math functions. – James Jun 29 '13 at 19:15
  • @chrislondon It is better to use (int) typecast. See my answer. – Nikhil Mohan Jun 29 '13 at 19:33
  • @Ohgodwhy number_format rounds, it doesn't truncate – Benubird Jul 22 '14 at 16:52

6 Answers6

27

Yes intval

intval(1234.567);
intval(-1234.567);
Martin
  • 22,212
  • 11
  • 70
  • 132
Manoj Yadav
  • 6,560
  • 1
  • 23
  • 21
11

Truncate floats with specific precision:

echo bcdiv(2.56789, 1, 1);  // 2.5
echo bcdiv(2.56789, 1, 3);  // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 3); // -2.567

This method solve the problem with round() function.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
pablorsk
  • 3,861
  • 1
  • 32
  • 37
  • 2
    This is good if you have the library to open, otherwise you'll get a fatal error: "Call to undefined function bcdiv()" – vr_driver Jul 09 '20 at 07:14
4

Also you can use typecasting (no need to use functions),

(int) 1234.567; //  1234
(int) -1234.567; // -1234

http://php.net/manual/en/language.types.type-juggling.php

You can see the difference between intval and (int) typecasting from here.

Community
  • 1
  • 1
Nikhil Mohan
  • 891
  • 6
  • 13
2

another hack is using prefix ~~ :

echo ~~1234.567; // 1234
echo ~~-1234.567; // 1234

it's simpler and faster

Tilde ~ is bitwise NOT operator in PHP and Javascript

Double tilde(~) is a quick way to cast variable as integer, where it is called 'two tildes' to indicate a form of double negation.

It removes everything after the decimal point because the bitwise operators implicitly convert their operands to signed 32-bit integers. This works whether the operands are (floating-point) numbers or strings, and the result is a number

reference:

Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73
1

you can use intval(number); but if your number bigger than 2147483648 (and your machine/os is x64) all bigs will be truncated to 2147483648. So you can use

if($number < 0 )
$res = round($number);
else
$res = floor($number); 

echo $res;
Ahmet Mehmet
  • 288
  • 2
  • 10
0

You can shift the decimal to the desired place, intval, and shift back:

function truncate($number, $precision = 0) {
   // warning: precision is limited by the size of the int type
   $shift = pow(10, $precision);
   return intval($number * $shift)/$shift;
}

Note the warning about size of int -- this is because $number is potentially being multiplied by a large number ($shift) which could make the resulting number too large to be stored as an integer type. Possibly converting to floating point might be better.

You could get fancy with a $base parameter, and sending that to intval(...).

Could (should) also get fancy with error/bounds checking.

An alternative approach would be to treat number as a string, find the decimal point and do a substring at the appropriate place after the decimal based on the desired precision. Relatively speaking, that won't be fast.

Mike T
  • 1,286
  • 11
  • 13