My favorite way to do this:
#!/usr/bin/perl -slw
use strict;
use warnings 'all';
use POSIX 'ceil';
our $N //= 3;
our $M //= 1e6;
my $each = ceil($M / $N);
my $last = 0;
my @ranges = ( );
for( 1..$N )
{
last unless $last <= $M;
my $part = [ $last => $_ == $N ? $M : $last + ( $_ == $N ? $each : $
+each - 1 ) ];
$part->[1] = $M if $_ == $N;
$last += $each;
push @ranges, $part;
}# end for()
printf "%2d : from %7d to %7d (%7d)\n",
$_, @{ $ranges[ $_ ] },
$ranges[ $_ ][ 1 ] - $ranges[ $_ ][ 0 ] + 1
for 0 .. $#ranges;
Produces the following:
john@e6510:~/Desktop$ ./ranges -N=1 -M=9999997
0 : from 0 to 9999997 (9999998)
john@e6510:~/Desktop$ ./ranges -N=2 -M=9999997
0 : from 0 to 4999998 (4999999)
1 : from 4999999 to 9999997 (4999999)
john@e6510:~/Desktop$ ./ranges -N=3 -M=9999997
0 : from 0 to 3333332 (3333333)
1 : from 3333333 to 6666665 (3333333)
2 : from 6666666 to 9999997 (3333332)
john@e6510:~/Desktop$ ./ranges -N=4 -M=9999997
0 : from 0 to 2499999 (2500000)
1 : from 2500000 to 4999999 (2500000)
2 : from 5000000 to 7499999 (2500000)
3 : from 7500000 to 9999997 (2499998)
john@e6510:~/Desktop$ ./ranges -N=5 -M=9999997
0 : from 0 to 1999999 (2000000)
1 : from 2000000 to 3999999 (2000000)
2 : from 4000000 to 5999999 (2000000)
3 : from 6000000 to 7999999 (2000000)
4 : from 8000000 to 9999997 (1999998)
Update: Now we properly calculate the number of ranges to create.
Update 2: This has a bug that I'm too tired and busy to figure out right now.