File Coverage

blib/lib/Number/Format/Calc.pm
Criterion Covered Total %
statement 120 124 96.7
branch 59 76 77.6
condition n/a
subroutine 41 43 95.3
pod 3 3 100.0
total 223 246 90.6


line stmt bran cond sub pod time code
1             package Number::Format::Calc;
2            
3 4     4   295570 use strict;
  4         43  
  4         134  
4 4     4   27 use warnings;
  4         8  
  4         128  
5            
6 4     4   1630 use Number::Format;
  4         50407  
  4         3117  
7            
8             our $VERSION = 0.21;
9            
10             my %defaults =
11             (
12             -thousands_sep => ",",
13             -decimal_point => ".",
14             );
15            
16             sub import
17             {
18 4     4   51 shift;
19 4         16 my %def = @_;
20 4         5143 $defaults{$_} = $def{$_} for keys %def;
21             }
22            
23             use overload
24            
25 106     106   2921 '""' => sub { $_[0]->{formatter}->format_number( $_[0]->{number} ) },
26            
27             #arithmetic operations
28 16     16   4820 '+' => sub { _operate ("+", @_); },
29 13     13   5974 '-' => sub { _operate ("-", @_); },
30 21     21   5871 '*' => sub { _operate ("*", @_); },
31 6     6   2931 '/' => sub { _operate ("/", @_); },
32 3     3   1307 '%' => sub { _operate ("%", @_); },
33 9     9   3978 '**' => sub { _operate ("**", @_); },
34            
35             #arithmetic operations with assign
36 2     2   736 '+=' => sub { _operatew ("+", @_); },
37 1     1   312 '-=' => sub { _operatew ("-", @_); },
38 3     3   753 '*=' => sub { _operatew ("*", @_); },
39 1     1   316 '/=' => sub { _operatew ("/", @_); },
40 0     0   0 '%=' => sub { _operatew ("%", @_); },
41 0     0   0 '**=' => sub { _operatew ("**", @_); },
42            
43             #arithmetic functions
44 1     1   8 'abs' => sub { _function ("abs", @_);},
45 1     1   7 'sqrt' => sub { _function ("sqrt",@_);},
46 1     1   311 'cos' => sub { _function ("cos", @_);},
47 1     1   301 'sin' => sub { _function ("sin", @_);},
48 1     1   3 'exp' => sub { _function ("exp", @_);},
49 1     1   313 'log' => sub { _function ("log", @_);},
50            
51             #mutations
52 6     6   2938 '++' => sub { _mutate ("++", @_); },
53 6     6   2600 '--' => sub { _mutate ("--", @_); },
54            
55             #numeric comparisons
56 1     1   4 '<' => sub { _compare ("<", @_); },
57 2     2   7 '<=' => sub { _compare ("<=", @_); },
58 1     1   303 '>' => sub { _compare (">", @_); },
59 2     2   6 '>=' => sub { _compare (">=", @_); },
60 1     1   4 '==' => sub { _compare ("==", @_); },
61 1     1   5 '!=' => sub { _compare ("!=", @_); },
62            
63             #numeric sorting
64 10     10   1045 '<=>' => sub { _numsort (@_); },
65            
66             #fallback
67 4     4   3304 fallback => 1;
  4         3494  
  4         184  
68            
69             #/use overload
70            
71             sub new
72             {
73 18     18 1 2860 my $class = shift;
74 18         37 my $number = shift;
75 18         71 my %args = @_;
76            
77 18         32 my %realargs = ();
78            
79            
80 18         64 for ( keys %args )
81             {
82 56         95 my $value = $args{$_};
83            
84 56         106 $_ = lc($_); s/^(?!-)/-/;
  56         136  
85            
86 56         123 $realargs{$_} = $value;
87             }
88            
89 18         62 for ( keys %defaults )
90             {
91 38         64 my $value = $defaults{$_};
92            
93 38         73 $_ = lc($_);
94 38         82 s/^(?!-)/-/;
95            
96 38 100       109 $realargs{$_} = $value unless exists $realargs{$_};
97             }
98            
99 18         51 my $self = bless {}, 'Number::Format::Calc';
100            
101 18         86 $self->{formatter} = new Number::Format (%realargs);
102 18         6112 $self->{number} = $self->{formatter}->unformat_number( $number );
103            
104 18         2245 return $self;
105             }
106            
107             sub _operate
108             {
109 68     68   171 my $op = shift;
110            
111 68 50       245 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
112 68 100       181 my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
113            
114 68         132 my $number = { %{$_[0]} };
  68         283  
115            
116 68 100       278 if ( $op eq "+" ) { $number->{number} = $op1 + $op2; }
  16 100       50  
    100          
    100          
    100          
    50          
117 13         32 elsif ( $op eq "-" ) { $number->{number} = $op1 - $op2; }
118 21         55 elsif ( $op eq "*" ) { $number->{number} = $op1 * $op2; }
119 6         21 elsif ( $op eq "/" ) { $number->{number} = $op1 / $op2; }
120 3         10 elsif ( $op eq "%" ) { $number->{number} = $op1 % $op2; }
121 9         41 elsif ( $op eq "**" ) { $number->{number} = $op1 ** $op2; }
122            
123 68         322 return bless $number, 'Number::Format::Calc';
124             }
125            
126             sub _operatew
127             {
128 7     7   14 my $op = shift;
129            
130 7 50       21 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
131 7 100       15 my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
132            
133 7 100       24 if ( $op eq "+" ) { $_[0]->{number} = $op1 + $op2; }
  2 100       6  
    100          
    50          
    0          
    0          
134 1         3 elsif ( $op eq "-" ) { $_[0]->{number} = $op1 - $op2; }
135 3         6 elsif ( $op eq "*" ) { $_[0]->{number} = $op1 * $op2; }
136 1         3 elsif ( $op eq "/" ) { $_[0]->{number} = $op1 / $op2; }
137 0         0 elsif ( $op eq "%" ) { $_[0]->{number} = $op1 % $op2; }
138 0         0 elsif ( $op eq "**" ) { $_[0]->{number} = $op1 ** $op2; }
139            
140 7         16 return $_[0];
141             }
142            
143            
144             sub _mutate
145             {
146 12     12   28 my $op = shift;
147            
148 12 100       48 if ( $op eq "++" ) { ++ $_[0]->{number} }
  6 50       29  
149 6         31 elsif ( $op eq "--" ) { -- $_[0]->{number} }
150             }
151            
152             sub _compare
153             {
154 8     8   12 my $op = shift;
155            
156 8 50       20 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
157 8 50       15 my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
158            
159 8 100       32 if ( $op eq "<" ) { return $op1 < $op2; }
  1 100       6  
    100          
    100          
    100          
    50          
160 1         4 elsif ( $op eq ">" ) { return $op1 > $op2; }
161 2         10 elsif ( $op eq "<=" ) { return $op1 <= $op2; }
162 2         18 elsif ( $op eq ">=" ) { return $op1 >= $op2; }
163 1         5 elsif ( $op eq "==" ) { return $op1 == $op2; }
164 1         6 elsif ( $op eq "!=" ) { return $op1 != $op2; }
165             }
166            
167             sub _numsort
168             {
169 10 50   10   20 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
170 10 50       19 my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
171            
172 10         23 return $op1 <=> $op2;
173             }
174            
175             sub _function
176             {
177 6     6   17 my $op = shift;
178            
179 6 50       16 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
180            
181 6         7 my $number = { %{$_[0]} };
  6         15  
182            
183 6 100       30 if ( $op eq "sqrt" ) { $number->{number} = sqrt($op1); }
  1 100       3  
    100          
    100          
    100          
    50          
184 1         4 elsif ( $op eq "abs" ) { $number->{number} = abs($op1); }
185 1         12 elsif ( $op eq "cos" ) { $number->{number} = cos($op1); }
186 1         19 elsif ( $op eq "sin" ) { $number->{number} = sin($op1); }
187 1         7 elsif ( $op eq "exp" ) { $number->{number} = exp($op1); }
188 1         5 elsif ( $op eq "log" ) { $number->{number} = log($op1); }
189            
190 6         21 return bless $number, 'Number::Format::Calc';
191             }
192            
193             sub number
194             {
195 1     1 1 319 return $_[0]->{number};
196             }
197            
198 4     4   7448 use Data::Dumper;
  4         21710  
  4         861  
199             sub fmod
200             {
201 2 50   2 1 296 my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
202 2 100       6 my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
203            
204 2         3 my $number = { %{$_[0]} };
  2         5  
205            
206 2         7 $number->{number} = $op1-(int($op1/$op2)*$op2);
207            
208 2         7 return bless $number, 'Number::Format::Calc';
209             }
210            
211             1;
212            
213            
214             =head1 NAME
215            
216             Number::Format::Calc
217            
218             =head1 SYNOPSIS
219            
220             use Number::Format::Calc (%args);
221             $n = new Number::Format::Calc ('1.234,5', %args );
222            
223             =head1 DESCRIPTION
224            
225             This module makes calculations with formatted numbers transparent.
226            
227             All arithmetric operators and and some arithmetric functions (I) are overloaded.
228            
229             =head1 METHODS
230            
231             =head2 new ($self, $number, %args)
232            
233             The constructor awaits the formatted number-string as the first argument,
234             and a hash with the same formatting-options as in Number::Format.
235            
236             The same arguments can be passed via the C-statement and will then serve as defaults
237             for all instances of Number::Format::Calc-objects.
238            
239             =head2 number ($self)
240            
241             This method returns the number without formats.
242            
243             =head2 fmod ($self, $foo)
244            
245             This method returns the result of a floating-point modulo operation from $self->number modulo $foo.
246            
247             =head1 Examples
248            
249             use Number::Format::Calc;
250            
251             my $n = new Number::Format::Calc ( '1.111,5' , -thousands_sep=>".", -decimal_point=>",", decimal_digits=>1 );
252             my $m = new Number::Format::Calc ( '2.222,35' , -thousands_sep=>".", -decimal_point=>",", decimal_digits=>2 );
253            
254             #add 10 to the object
255             print $n + 10, "\n"; #1.121,5;
256            
257             #When two objects are involved, the settings of the left object win:
258             print $n + $m, "\n"; #3.333,9;
259             print $m + $n, "\n"; #3.333,85;
260            
261             #modulo operation
262             print $n % 9, "\n"; #4
263            
264             #floating-point modulo operation
265             print $n->fmod(9), "\n"; #4.5
266            
267             #Get plain number
268             print $n->number; #1111.5
269            
270             More examples can be found in the test-files (*.t) that come with this module.
271            
272             ########################################################################
273            
274             #using defaults
275             use Number::Format::Calc ( -thousands_sep=>".", -decimal_point=>",", -decimal_digits=>2, -decimal_fill => 1 );
276            
277             my $n = new Number::Format::Calc ('1.111,5');
278             print $n; #1.111,50
279            
280            
281             =head1 PREREQUISITIES
282            
283             Number::Format
284             Test::Simple
285            
286             =head1 BUGS
287            
288             None that I know of. If you find one, or a missing test-case, let me know.
289            
290             =head1 AUTHOR
291            
292             Markus Holzer
293             CPAN ID: HOLLIHO
294             HOLLIHO@gmx.de
295             http://holli.perlmonk.org
296            
297             You can also reach me via the chatterbox at L
298            
299             =head1 COPYRIGHT
300            
301             This program is free software licensed under the...
302            
303             The General Public License (GPL)
304             Version 2, June 1991
305            
306             The full text of the license can be found in the
307             LICENSE file included with this module.
308            
309            
310             =head1 SEE ALSO
311            
312             perl(1).
313            
314             =cut
315            
316             ############################################# main pod documentation end ##