5
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
9
@ISA = qw(Exporter AutoLoader);
10
@EXPORT = qw(round nearest);
11
@EXPORT_OK = qw(round nearest round_even round_odd round_rand
12
nearest_ceil nearest_floor nearest_rand
16
%EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
18
#--- Determine what value to use for "one-half". Because of the
19
#--- perversities of floating-point hardware, we must use a value
20
#--- slightly larger than 1/2. We accomplish this by determining
21
#--- the bit value of 0.5 and increasing it by a small amount in a
22
#--- lower-order byte. Since the lowest-order bits are still zero,
23
#--- the number is mathematically exact.
25
my $halfhex = unpack('H*', pack('d', 0.5));
26
if (substr($halfhex,0,2) ne '00' && substr($halfhex, -2) eq '00') {
28
substr($halfhex, -4) = '1000';
30
#--- It's little-endian.
31
substr($halfhex, 0,4) = '0010';
34
my $half = unpack('d',pack('H*', $halfhex));
41
push @res, POSIX::floor($x + $half);
43
push @res, POSIX::ceil($x - $half);
46
return (wantarray) ? @res : $res[0];
53
my ($sign, $in, $fr) = _sepnum($x);
55
push @res, $sign * (($in % 2 == 0) ? $in : $in + 1);
57
push @res, $sign * POSIX::floor(abs($x) + $half);
60
return (wantarray) ? @res : $res[0];
67
my ($sign, $in, $fr) = _sepnum($x);
69
push @res, $sign * (($in % 2 == 1) ? $in : $in + 1);
71
push @res, $sign * POSIX::floor(abs($x) + $half);
74
return (wantarray) ? @res : $res[0];
81
my ($sign, $in, $fr) = _sepnum($x);
83
push @res, $sign * ((rand(4096) < 2048) ? $in : $in + 1);
85
push @res, $sign * POSIX::floor(abs($x) + $half);
88
return (wantarray) ? @res : $res[0];
91
#--- Separate a number into sign, integer, and fractional parts.
92
#--- Return as a list.
96
$sign = ($x >= 0) ? 1 : -1;
99
return ($sign, $i, $x - $i);
102
#------ "Nearest" routines (round to a multiple of any number)
105
my ($targ, @inputs) = @_;
109
$targ = abs($targ) if $targ < 0;
110
foreach $x (@inputs) {
112
push @res, $targ * int(($x + $half * $targ) / $targ);
114
push @res, $targ * POSIX::ceil(($x - $half * $targ) / $targ);
117
return (wantarray) ? @res : $res[0];
120
# In the next two functions, the code for positive and negative numbers
121
# turns out to be the same. For negative numbers, the technique is not
122
# exactly obvious; instead of floor(x+0.5), we are in effect taking
126
my ($targ, @inputs) = @_;
130
$targ = abs($targ) if $targ < 0;
131
foreach $x (@inputs) {
132
push @res, $targ * POSIX::floor(($x + $half * $targ) / $targ);
134
return (wantarray) ? @res : $res[0];
138
my ($targ, @inputs) = @_;
142
$targ = abs($targ) if $targ < 0;
143
foreach $x (@inputs) {
144
push @res, $targ * POSIX::ceil(($x - $half * $targ) / $targ);
146
return (wantarray) ? @res : $res[0];
150
my ($targ, @inputs) = @_;
154
$targ = abs($targ) if $targ < 0;
155
foreach $x (@inputs) {
156
my ($sign, $in, $fr) = _sepnear($x, $targ);
157
if ($fr == 0.5 * $targ) {
158
push @res, $sign * $targ * ((rand(4096) < 2048) ? $in : $in + 1);
160
push @res, $sign * $targ * int((abs($x) + $half * $targ) / $targ);
163
return (wantarray) ? @res : $res[0];
166
#--- Next lower multiple
168
my ($targ, @inputs) = @_;
172
$targ = abs($targ) if $targ < 0;
173
foreach $x (@inputs) {
174
push @res, $targ * POSIX::floor($x / $targ);
176
return (wantarray) ? @res : $res[0];
179
#--- Next higher multiple
181
my ($targ, @inputs) = @_;
185
$targ = abs($targ) if $targ < 0;
186
foreach $x (@inputs) {
187
push @res, $targ * POSIX::ceil($x / $targ);
189
return (wantarray) ? @res : $res[0];
192
#--- Separate a number into sign, "integer", and "fractional" parts
193
#--- for the 'nearest' calculation. Return as a list.
197
$sign = ($x >= 0) ? 1 : -1;
199
$i = int($x / $targ);
200
return ($sign, $i, $x - $i*$targ);
209
Math::Round - Perl extension for rounding numbers
213
use Math::Round qw(...those desired... or :all);
215
$rounded = round($scalar);
216
@rounded = round(LIST...);
217
$rounded = nearest($target, $scalar);
218
@rounded = nearest($target, LIST...);
220
# and other functions as described below
224
B<Math::Round> supplies functions that will round numbers in different
225
ways. The functions B<round> and B<nearest> are exported by
226
default; others are available as described below. "use ... qw(:all)"
227
exports all functions.
235
Rounds the number(s) to the nearest integer. In scalar context,
236
returns a single value; in list context, returns a list of values.
237
Numbers that are halfway between two integers are rounded
238
"to infinity"; i.e., positive values are rounded up (e.g., 2.5
239
becomes 3) and negative values down (e.g., -2.5 becomes -3).
241
=item B<round_even> LIST
243
Rounds the number(s) to the nearest integer. In scalar context,
244
returns a single value; in list context, returns a list of values.
245
Numbers that are halfway between two integers are rounded to the
246
nearest even number; e.g., 2.5 becomes 2, 3.5 becomes 4, and -2.5
249
=item B<round_odd> LIST
251
Rounds the number(s) to the nearest integer. In scalar context,
252
returns a single value; in list context, returns a list of values.
253
Numbers that are halfway between two integers are rounded to the
254
nearest odd number; e.g., 3.5 becomes 3, 4.5 becomes 5, and -3.5
257
=item B<round_rand> LIST
259
Rounds the number(s) to the nearest integer. In scalar context,
260
returns a single value; in list context, returns a list of values.
261
Numbers that are halfway between two integers are rounded up or
262
down in a random fashion. For example, in a large number of trials,
263
2.5 will become 2 half the time and 3 half the time.
265
=item B<nearest> TARGET, LIST
267
Rounds the number(s) to the nearest multiple of the target value.
268
TARGET must be positive.
269
In scalar context, returns a single value; in list context, returns
270
a list of values. Numbers that are halfway between two multiples
271
of the target will be rounded to infinity. For example:
273
nearest(10, 44) yields 40
277
nearest(.1, 4.567) 4.6
280
=item B<nearest_ceil> TARGET, LIST
282
Rounds the number(s) to the nearest multiple of the target value.
283
TARGET must be positive.
284
In scalar context, returns a single value; in list context, returns
285
a list of values. Numbers that are halfway between two multiples
286
of the target will be rounded to the ceiling, i.e. the next
287
algebraically higher multiple. For example:
289
nearest_ceil(10, 44) yields 40
290
nearest_ceil(10, 45) 50
291
nearest_ceil(10, -45) -40
293
=item B<nearest_floor> TARGET, LIST
295
Rounds the number(s) to the nearest multiple of the target value.
296
TARGET must be positive.
297
In scalar context, returns a single value; in list context, returns
298
a list of values. Numbers that are halfway between two multiples
299
of the target will be rounded to the floor, i.e. the next
300
algebraically lower multiple. For example:
302
nearest_floor(10, 44) yields 40
303
nearest_floor(10, 45) 40
304
nearest_floor(10, -45) -50
306
=item B<nearest_rand> TARGET, LIST
308
Rounds the number(s) to the nearest multiple of the target value.
309
TARGET must be positive.
310
In scalar context, returns a single value; in list context, returns
311
a list of values. Numbers that are halfway between two multiples
312
of the target will be rounded up or down in a random fashion.
313
For example, in a large number of trials, C<nearest(10, 45)> will
314
yield 40 half the time and 50 half the time.
316
=item B<nlowmult> TARGET, LIST
318
Returns the next lower multiple of the number(s) in LIST.
319
TARGET must be positive.
320
In scalar context, returns a single value; in list context, returns
321
a list of values. Numbers that are between two multiples of the
322
target will be adjusted to the nearest multiples of LIST that are
323
algebraically lower. For example:
325
nlowmult(10, 44) yields 40
327
nlowmult(25, 328) 325
328
nlowmult(.1, 4.567) 4.5
329
nlowmult(10, -41) -50
331
=item B<nhimult> TARGET, LIST
333
Returns the next higher multiple of the number(s) in LIST.
334
TARGET must be positive.
335
In scalar context, returns a single value; in list context, returns
336
a list of values. Numbers that are between two multiples of the
337
target will be adjusted to the nearest multiples of LIST that are
338
algebraically higher. For example:
340
nhimult(10, 44) yields 50
343
nhimult(.1, 4.512) 4.6
348
=head1 STANDARD FLOATING-POINT DISCLAIMER
350
Floating-point numbers are, of course, a rational subset of the real
351
numbers, so calculations with them are not always exact. In order to
352
avoid surprises because of this, these routines use a value for
353
one-half that is very slightly larger than 0.5. Nevertheless,
354
if the numbers to be rounded are stored as floating-point, they will
355
be subject, as usual, to the mercies of your hardware, your C
356
compiler, etc. Thus, numbers that are supposed to be halfway between
357
two others may be stored in a slightly different way and thus behave
362
Math::Round was written by Geoffrey Rommel E<lt>GROMMEL@cpan.orgE<gt>