@@ -24,7 +24,7 @@ Number::Format - Perl extension for formatting numbers
24
24
$number = $x->unformat_number($formatted);
25
25
26
26
use Number::Format qw(:subs);
27
- $formatted = round($number, $precision);
27
+ $formatted = round($number, $precision, $roundoption );
28
28
$formatted = format_number($number, $precision, $trailing_zeroes);
29
29
$formatted = format_negative($number, $picture);
30
30
$formatted = format_picture($number, $picture);
@@ -59,6 +59,7 @@ formatting engine. Valid parameters are:
59
59
DECIMAL_DIGITS - number of digits to the right of dec point (def 2)
60
60
DECIMAL_FILL - boolean; whether to add zeroes to fill out decimal
61
61
NEG_FORMAT - format to display negative numbers (def ``-x'')
62
+ ROUND_OPTION - decide to floor or normal rounding or ceil
62
63
KILO_SUFFIX - suffix to add when format_bytes formats kilobytes (trad)
63
64
MEGA_SUFFIX - " " " " " " megabytes (trad)
64
65
GIGA_SUFFIX - " " " " " " gigabytes (trad)
@@ -100,6 +101,7 @@ the parameters are:
100
101
DECIMAL_DIGITS = 2
101
102
DECIMAL_FILL = 0
102
103
NEG_FORMAT = '-x'
104
+ ROUND_OPTION = 0
103
105
KILO_SUFFIX = 'K'
104
106
MEGA_SUFFIX = 'M'
105
107
GIGA_SUFFIX = 'G'
@@ -127,6 +129,9 @@ positive representation of the number being passed to that function.
127
129
C<format_number() > and C<format_price() > utilize this feature by
128
130
calling C<format_negative() > if the number was less than 0.
129
131
132
+ C<ROUND_OPTION > is only used by C<round() > . A number less then 0 means
133
+ floor, a number bigger then 0 ceil and a 0 stand for a normal rounding.
134
+
130
135
C<KILO_SUFFIX > , C<MEGA_SUFFIX > , and C<GIGA_SUFFIX > are used by
131
136
C<format_bytes() > when the value is over 1024, 1024*1024, or
132
137
1024*1024*1024, respectively. The default values are "K", "M", and
@@ -195,7 +200,7 @@ our @EXPORT_LC_MONETARY =
195
200
$N_CS_PRECEDES $N_SEP_BY_SPACE $P_SIGN_POSN $N_SIGN_POSN ) ;
196
201
197
202
our @EXPORT_OTHER =
198
- qw( $DECIMAL_DIGITS $DECIMAL_FILL $NEG_FORMAT
203
+ qw( $DECIMAL_DIGITS $DECIMAL_FILL $NEG_FORMAT $ROUND_OPTION
199
204
$KILO_SUFFIX $MEGA_SUFFIX $GIGA_SUFFIX
200
205
$KIBI_SUFFIX $MEBI_SUFFIX $GIBI_SUFFIX ) ;
201
206
@@ -242,6 +247,7 @@ our $N_SIGN_POSN = 1; # sign rules for negative: 0-4
242
247
our $DECIMAL_DIGITS = 2;
243
248
our $DECIMAL_FILL = 0;
244
249
our $NEG_FORMAT = ' -x' ;
250
+ our $ROUND_OPTION = 0;
245
251
our $KILO_SUFFIX = ' K' ;
246
252
our $MEGA_SUFFIX = ' M' ;
247
253
our $GIGA_SUFFIX = ' G' ;
@@ -276,6 +282,7 @@ our $DEFAULT_LOCALE = { (
276
282
decimal_digits => $DECIMAL_DIGITS ,
277
283
decimal_fill => $DECIMAL_FILL ,
278
284
neg_format => $NEG_FORMAT ,
285
+ round_option => $ROUND_OPTION ,
279
286
kilo_suffix => $KILO_SUFFIX ,
280
287
mega_suffix => $MEGA_SUFFIX ,
281
288
giga_suffix => $GIGA_SUFFIX ,
@@ -482,18 +489,25 @@ sub new
482
489
483
490
# #----------------------------------------------------------------------
484
491
485
- =item round($number, $precision)
492
+ =item round($number, $precision, $roundoption )
486
493
487
494
Rounds the number to the specified precision. If C<$precision > is
488
495
omitted, the value of the C<DECIMAL_DIGITS > parameter is used (default
489
496
value 2). Both input and output are numeric (the function uses math
490
497
operators rather than string manipulation to do its job), The value of
491
- C<$precision > may be any integer, positive or negative. Examples:
492
-
493
- round(3.14159) yields 3.14
494
- round(3.14159, 4) yields 3.1416
495
- round(42.00, 4) yields 42
496
- round(1234, -2) yields 1200
498
+ C<$precision > may be any integer, positive or negative. If C<$roundoption >
499
+ is omitted, the value of the C<ROUND_OPTION > paramter is used (default
500
+ value 0). Examples:
501
+
502
+ round(3.14159) yields 3.14
503
+ round(3.14159, undef, 1) yields 3.15
504
+ round(3.14159, undef, -1) yields 3.14
505
+ round(3.14159, 4) yields 3.1416
506
+ round(42.00, 4) yields 42
507
+ round(1234, -2) yields 1200
508
+ round(1234, -2, 1) yields 1300
509
+ round(1298, -2) yields 1300
510
+ round(1298, -2, -1) yields 1200
497
511
498
512
Since this is a mathematical rather than string oriented function,
499
513
there will be no trailing zeroes to the right of the decimal point,
@@ -505,24 +519,39 @@ variables, use C<format_number()> instead.
505
519
506
520
sub round
507
521
{
508
- my ($self , $number , $precision ) = _get_self @_ ;
522
+ my ($self , $number , $precision , $roundoption ) = _get_self @_ ;
509
523
510
524
unless (defined ($number ))
511
525
{
512
526
_complain_undef();
513
527
$number = 0;
514
528
}
515
529
516
- $precision = $self -> {decimal_digits } unless defined $precision ;
517
- $precision = 2 unless defined $precision ;
530
+ $precision = $self -> {decimal_digits } unless defined $precision ;
531
+ $precision = 2 unless defined $precision ;
532
+ $roundoption = $self -> {round_option } unless defined $roundoption ;
533
+ $roundoption = 0 unless defined $roundoption ;
518
534
519
535
croak(" precision must be integer" )
520
536
unless int ($precision ) == $precision ;
521
537
522
538
if (ref ($number ) && $number -> isa(" Math::BigFloat" ))
523
539
{
524
540
my $rounded = $number -> copy();
525
- $rounded -> precision(-$precision );
541
+
542
+ if ($roundoption ) {
543
+ $rounded *= 10**$precision ;
544
+ if ($roundoption < 0) {
545
+ $rounded -> bfloor();
546
+ }
547
+ elsif ($roundoption > 0) {
548
+ $rounded -> bceil();
549
+ }
550
+ $rounded /= 10**$precision ;
551
+ }
552
+
553
+ $rounded -> round(0, -$precision );
554
+
526
555
return $rounded ;
527
556
}
528
557
@@ -536,8 +565,31 @@ sub round
536
565
537
566
# We need to add 1e-14 to avoid some rounding errors due to the
538
567
# way floating point numbers work - see string-eq test in t/round.t
539
- $result = int ($product + .5 + 1e-14) / $multiplier ;
540
- $result = -$result if $sign < 0;
568
+ if ($roundoption < 0) {
569
+ if ($sign < 0) {
570
+ $result = int ($product + 1 - 1e-14) / -$multiplier ;
571
+ }
572
+ else {
573
+ $result = int ($product ) / $multiplier ;
574
+ }
575
+ }
576
+ elsif ($roundoption == 0) {
577
+ if ($sign < 0) {
578
+ $result = int ($product + 0.5 + 1e-14) / -$multiplier ;
579
+ }
580
+ else {
581
+ $result = int ($product + 0.5 + 1e-14) / $multiplier ;
582
+ }
583
+ }
584
+ else {
585
+ if ($sign < 0) {
586
+ $result = int ($product ) / -$multiplier ;
587
+ }
588
+ else {
589
+ $result = int ($product + 1 - 1e-14) / $multiplier ;
590
+ }
591
+ }
592
+
541
593
return $result ;
542
594
}
543
595
0 commit comments