65

What is a good way to always do integer division in Perl?

For example, I want:

real / int = int

int / real = int

int / int = int
GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Bryan Denny
  • 27,363
  • 32
  • 109
  • 125

7 Answers7

93

There are at least 2 reasonable answers to this question. (I originally gave only answer 2.)

  1. Use the int() function to truncate the floating-point calculation result to an integer (throwing away the decimal part), as Bryan suggested in his self-answer: #539805

  2. Use the use integer pragma to make Perl truncate both the inputs and results of calculations to integers. It's scoped to within { } blocks.

Examples:

print 3.0/2.1 . "\n";      # => 1.42857142857143
print 5.0/1.5 . "\n";      # => 3.33333333333333

print int(3.0/2.1) . "\n"; # => 1
print int(5.0/1.5) . "\n"; # => 3

{
  use integer;
  print 3.0/2.1 . "\n";    # => 1
  print 5.0/1.5 . "\n";    # => 5 (because 1.5 was truncated to 1)
}
print 3.0/2.1 . "\n";      # => 1.42857142857143 again
Michael Ratanapintha
  • 39,422
  • 4
  • 33
  • 40
  • 1
    Additional info, parentheses separate 'use integer' inside block, then outside the block, will be used standard real calculation both before and after block. – Znik Feb 22 '18 at 13:09
  • Without using 'use integer' you can always write -1 & $x which returns the integer value of $x ... – johannesvalks Jun 15 '20 at 21:42
  • @johannesvalks That will turn negative integers into positive twos-complement numbers, which is probably not what you wanted. 'use integer' is also problematic, as it is *signed* integers, so will completely screw up large unsigned numbers. use integer also has implementation defined behavior with negative inputs on C89 compilers. Casting via int(a/b) is going to be wrong for most large inputs. Getting consistent results for all inputs is *really* hard. – DanaJ Feb 21 '21 at 05:06
  • You are changing the definition of "integer division" in the entire history of modern computing and perhaps mathematics! See the link for what integer division actually is. Your method yields 5 for 5/1.5, while integer division yields 3. https://www.ibm.com/docs/en/zvse/6.2?topic=SSB27H_6.2.0/fg1rr_integer_division.html – FNia Feb 16 '22 at 04:14
  • Fair point @FNia, although that meaning was Perl's choice, not mine. I revised my answer. – Michael Ratanapintha Feb 17 '22 at 00:19
  • @MichaelRatanapintha Thanks for the revision. I'm not sure if Perl officially refers to that method a "integer division", but if I've missed it in the docs please point to it. – FNia Feb 18 '22 at 01:42
51

You can cast ints in Perl:

int(5/1.5) = 3;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bryan Denny
  • 27,363
  • 32
  • 109
  • 125
  • 9
    Yes, but integer division would be int(5) / int(1.5). Otherwise, you're just rounding the real division. – Rog Feb 12 '09 at 02:56
  • 7
    but int(5) / int(1.5) != int – Learning Feb 12 '09 at 02:59
  • 5
    Sorry, this is what I was really asking for. I was wanting an int result after doing any sort of division. So yes, I was looking for rounding. – Bryan Denny Feb 12 '09 at 16:06
  • 3
    Beware floating point rounding problems: `int(-6.725/0.025)` is -268 and `POSIX::floor(-6.725/0.025)` is -269 [see perldoc](http://perldoc.perl.org/functions/int.html) – maxpolk Apr 22 '16 at 18:36
  • 5
    It is completly wrong, because with intiger division we completly drop all numbers after dot. then with int math 5/1.5 is 5/1 eq 5 not 3 as in this example. Also it is wrong when we round up/down numbers, then 5/1.5 is 5/2 eq 2.5=>3, but it equals witn int(5/1.5) by accident. it is not rule. – Znik Feb 22 '17 at 08:38
  • 1
    The comments here are confusing and quite wrong in some cases. If you're looking for integer division the way it works in C (where all values after the decimal are _truncated_, not _rounded_) this answer will work. Note though that as @maxpolk points out, the perl docs recommend `POSIX::floor`. – Shane Hughes Dec 11 '18 at 12:56
  • 1
    @ShaneHughes I agree with Shane. "Integer division" is truncation (not rounding) after dividing -- it doesn't mean that the inputs are truncated first, so Rog and Znik are quite wrong. I don't know of any language so broken that dividing 5 by 1.5 yields 5 ... not `int(5/1.5)` in C++ or `(int)(5/1.5)` in C or `5//1.5` in Python. P.S. Hah! The exception! `use integer;` in perl ... but that's brain damaged. – Jim Balter Aug 12 '19 at 01:12
8

int(x+.5) will round positive values toward the nearest integer. Rounding up is harder.

To round toward zero:

int($x)

For the solutions below, include the following statement:

use POSIX;

To round down: POSIX::floor($x)

To round up: POSIX::ceil($x)

To round away from zero: POSIX::floor($x) - int($x) + POSIX::ceil($x)

To round off to the nearest integer: POSIX::floor($x+.5)

Note that int($x+.5) fails badly for negative values. int(-2.1+.5) is int(-1.6), which is -1.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 4
    No, `int` rounds toward zero, while normal rounding it toward even. Run `perl -le 'printf "int(%s) is %d, round(%s) is %.0f;\n", ($_+0.5)x4 for -10..10'` and you will see things like int(-3.5) is -3, round(-3.5) is -4; int(-2.5) is -2, round(-2.5) is -2; int(-1.5) is -1, round(-1.5) is -2; int(-0.5) is 0, round(-0.5) is -0; int(0.5) is 0, round(0.5) is 0; int(1.5) is 1, round(1.5) is 2; int(2.5) is 2, round(2.5) is 2; int(3.5) is 3, round(3.5) is 4; int(4.5) is 4, round(4.5) is 4; – tchrist May 05 '11 at 02:17
  • @tchrist Actually, normal rounding is towards nearest; only the border case .5 rounds towards even. – fishinear Aug 09 '17 at 13:18
4

you can:

use integer;

it is explained by Michael Ratanapintha or else use manually:

$a=3.7;
$b=2.1;

$c=int(int($a)/int($b));

notice, 'int' is not casting. this is function for converting number to integer form. this is because Perl 5 does not have separate integer division. exception is when you 'use integer'. Then you will lose real division.

Znik
  • 1,047
  • 12
  • 17
0

Hope it works

int(9/4) = 2.

Thanks Manojkumar

0

Integer division $x divided by $y ...

$z = -1 & $x / $y

How does it work?

$x / $y

return the floating point division

&

perform a bit-wise AND

-1

stands for

&HFFFFFFFF

for the largest integer ... whence

$z = -1 & $x / $y

gives the integer division ...

  • `perl -E 'my($x,$y)=(-12,4); my $z = -1 & $x/$y; say int($x/$y); say $x/$y; say $z;'` will give: -3, -3, 18446744073709551613. – DanaJ Feb 21 '21 at 05:12
-2

Eg 9 / 4 = 2.25

int(9) / int(4) = 2

9 / 4 - remainder / deniminator = 2

9 /4 - 9 % 4 / 4 = 2

Paul
  • 1