File Coverage

blib/lib/Number/Format/Calc.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Number::Format::Calc;
2            
3 4     4   103708 use strict;
  4         10  
  4         173  
4 4     4   23 use warnings;
  4         9  
  4         142  
5            
6 4     4   7047 use Number::Format;
  0            
  0            
7            
8             our $VERSION = 0.1;
9            
10             my %defaults =
11             (
12             -thousands_sep => ",",
13             -decimal_point => ".",
14             );
15            
16             sub import
17             {
18             shift;
19             my %def = @_;
20             $defaults{$_} = $def{$_} for keys %def;
21             }
22            
23             use overload
24            
25             '""' => sub { $_[0]->{formatter}->format_number( $_[0]->{number} ) },
26            
27             #arithmetic operations
28             '+' => sub { _operate ("+", @_); },
29             '-' => sub { _operate ("-", @_); },
30             '*' => sub { _operate ("*", @_); },
31             '/' => sub { _operate ("/", @_); },
32             '%' => sub { _operate ("%", @_); },
33             '**' => sub { _operate ("**", @_); },
34            
35             #arithmetic operations with assign
36             '+=' => sub { _operatew ("+", @_); },
37             '-=' => sub { _operatew ("-", @_); },
38             '*=' => sub { _operatew ("*", @_); },
39             '/=' => sub { _operatew ("/", @_); },
40             '%=' => sub { _operatew ("%", @_); },
41             '**=' => sub { _operatew ("**", @_); },
42            
43             #arithmetic functions
44             'abs' => sub { _function ("abs", @_);},
45             'sqrt' => sub { _function ("sqrt",@_);},
46             'cos' => sub { _function ("cos", @_);},
47             'sin' => sub { _function ("sin", @_);},
48             'exp' => sub { _function ("exp", @_);},
49             'log' => sub { _function ("log", @_);},
50            
51             #mutations
52             '++' => sub { _mutate ("++", @_); },
53             '--' => sub { _mutate ("--", @_); },
54            
55             #numeric comparisons
56             '<' => sub { _compare ("<", @_); },
57             '<=' => sub { _compare ("<=", @_); },
58             '>' => sub { _compare (">", @_); },
59             '>=' => sub { _compare (">=", @_); },
60             '==' => sub { _compare ("==", @_); },
61             '!=' => sub { _compare ("!=", @_); },
62            
63             #numeric sorting
64             '<=>' => sub { _numsort (@_); },
65            
66             #fallback
67             fallback => 1;
68            
69             #/use overload
70            
71             sub new
72             {
73             my $class = shift;
74             my $number = shift;
75             my %args = @_;
76            
77             my %realargs = ();
78              
79              
80             for ( keys %args )
81             {
82             my $value = $args{$_};
83            
84             $_ = lc($_); s/^(?!-)/-/;
85            
86             $realargs{$_} = $value;
87             }
88            
89             for ( keys %defaults )
90             {
91             my $value = $defaults{$_};
92            
93             $_ = lc($_);
94             s/^(?!-)/-/;
95            
96             $realargs{$_} = $value unless exists $realargs{$_};
97             }
98            
99             my $self = bless {}, 'Number::Format::Calc';
100            
101             $self->{formatter} = new Number::Format (%realargs);
102             $self->{number} = $self->{formatter}->unformat_number( $number );
103            
104             return $self;
105             }
106            
107             sub _operate
108             {
109             my $op = shift;
110            
111             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
112             my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
113            
114             my $number = { %{$_[0]} };
115            
116             if ( $op eq "+" ) { $number->{number} = $op1 + $op2; }
117             elsif ( $op eq "-" ) { $number->{number} = $op1 - $op2; }
118             elsif ( $op eq "*" ) { $number->{number} = $op1 * $op2; }
119             elsif ( $op eq "/" ) { $number->{number} = $op1 / $op2; }
120             elsif ( $op eq "%" ) { $number->{number} = $op1 % $op2; }
121             elsif ( $op eq "**" ) { $number->{number} = $op1 ** $op2; }
122            
123             return bless $number, 'Number::Format::Calc';
124             }
125            
126             sub _operatew
127             {
128             my $op = shift;
129            
130             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
131             my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
132            
133             if ( $op eq "+" ) { $_[0]->{number} = $op1 + $op2; }
134             elsif ( $op eq "-" ) { $_[0]->{number} = $op1 - $op2; }
135             elsif ( $op eq "*" ) { $_[0]->{number} = $op1 * $op2; }
136             elsif ( $op eq "/" ) { $_[0]->{number} = $op1 / $op2; }
137             elsif ( $op eq "%" ) { $_[0]->{number} = $op1 % $op2; }
138             elsif ( $op eq "**" ) { $_[0]->{number} = $op1 ** $op2; }
139            
140             return $_[0];
141             }
142            
143            
144             sub _mutate
145             {
146             my $op = shift;
147            
148             if ( $op eq "++" ) { ++ $_[0]->{number} }
149             elsif ( $op eq "--" ) { -- $_[0]->{number} }
150             }
151            
152             sub _compare
153             {
154             my $op = shift;
155            
156             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
157             my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
158            
159             if ( $op eq "<" ) { return $op1 < $op2; }
160             elsif ( $op eq ">" ) { return $op1 > $op2; }
161             elsif ( $op eq "<=" ) { return $op1 <= $op2; }
162             elsif ( $op eq ">=" ) { return $op1 >= $op2; }
163             elsif ( $op eq "==" ) { return $op1 == $op2; }
164             elsif ( $op eq "!=" ) { return $op1 != $op2; }
165             }
166            
167             sub _numsort
168             {
169             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
170             my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
171            
172             return $op1 <=> $op2;
173             }
174            
175             sub _function
176             {
177             my $op = shift;
178            
179             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
180            
181             my $number = { %{$_[0]} };
182            
183             if ( $op eq "sqrt" ) { $number->{number} = sqrt($op1); }
184             elsif ( $op eq "abs" ) { $number->{number} = abs($op1); }
185             elsif ( $op eq "cos" ) { $number->{number} = cos($op1); }
186             elsif ( $op eq "sin" ) { $number->{number} = sin($op1); }
187             elsif ( $op eq "exp" ) { $number->{number} = exp($op1); }
188             elsif ( $op eq "log" ) { $number->{number} = log($op1); }
189            
190             return bless $number, 'Number::Format::Calc';
191             }
192            
193             sub number
194             {
195             return $_[0]->{number};
196             }
197            
198             use Data::Dumper;
199             sub fmod
200             {
201             my $op1 = ref( $_[0] ) ? $_[0]->{number} : $_[0];
202             my $op2 = ref( $_[1] ) ? $_[1]->{number} : $_[1];
203            
204             my $number = { %{$_[0]} };
205            
206             $number->{number} = $op1-(int($op1/$op2)*$op2);
207            
208             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 ##