use strict; use Test::More; use Math::Round; my $tests = [ [ '0', 43, '43', 'Can go past one digit.'], [ '0', 4.4003, '4', 'Rounds down to 4'], [ '0', 4.5003, '5', 'Rounds up to 5'], [ '0', 400.5003, '401', 'Rounds up to 5'], [ '0', -34, '-34', 'no change to negative values'], [ '#0', 4.5003, '5', 'Rounds up to 5'], [ '#0', 99.5003, '100', 'rounds up to 100'], [ '#0', 43, '43', 'as expected'], [ '#0', 4, '4', ''], [ '#0', 3.45E-4, '0', 'exponent negative rounded to zero'], [ '#0', 3.45E+4, '34500', 'exponent real ok.'], [ '00', 43, '43', ''], [ '00', 3, '03', ''], [ '00', 999, '999', ''], [ '00', 43, '43', ''], [ '0.0', 43.333, '43.3', ''], [ '0.0', -43.333, '-43.3', ''], [ '0.0', 44.35, '44.4', 'Floating rounded up.'], [ '#0.00', 43.3, '43.30', ''], [ '#0.00', 3.3, '3.30', ''], [ '#0.00', 43.3, '43.30', ''], [ '0.00', 43.3, '43.30', ''], [ '0.00', 43.3, '43.30', ''], [ '0.00', 43.3, '43.30', ''], [ '0000', 43, '0043', ''], [ '##0.000', 43.3, '43.300', ''], [ '0.000', 43.3, '43.300', ''], [ '00.00', 43.3, '43.30', ''], [ '000.0', 43.3, '043.3', ''], [ '0.0000', 43.3, '43.3000', ''], [ '000.00', 43.3, '043.30', ''], [ '000000', 43, '000043', ''], ['000.0000', 43.3, '043.3000', ''], ['0.00E-00', 43.3, '4.33E+01', ''], ['0.00E+00', 43.3, '4.33E+01', ''], ]; plan tests => scalar(@$tests); foreach my $test (@$tests) { my $result = formatString($test->[1], $test->[0]); printf("Pattern:[%s] Value:[%s], ExpectedResult:[%s] Result:[%s]\n", @{$test}[0 .. 2], $result); is($result, $test->[2], $test->[3]); } sub formatString { my $value = shift; my $text = shift; my $debug = shift; my $workingValue = $value; # # will either be a digit or not. It doesn't appear to have any affect on the result. # # 0 will be either 0 or a digit. # 0.00E-00 is a scientific example. # $text =~ s/^#+//; # # doesn't do much at all. my $beforeDotRE = qr{^([\d]+)}; # stuff before the decimal (if there is one) my $afterDotRE = qr{\.(\d*)(E[+-](\d+))?$}; # stuff after the decimal. my $scientificRE = qw{E[+-](\d+)$}; # Scientific ending. my $textLength = length($text); my $beforeDot =''; my $beforeDotLen =0; if($text =~ m{$beforeDotRE}) { $beforeDot = $1; $beforeDotLen = length($beforeDot); } my $afterDot =''; my $afterDotLen =0; if($text =~ m{$afterDotRE}) { $afterDot = $1; $afterDotLen = length($afterDot); } my $scientific =''; my $scientificLen =0; if($text =~ m{$scientificRE}) { $scientific = $1; $scientificLen = length($scientific); } if($debug) { printf "Done Analyzing:[%s]\n", $text; printf "Format Length: [%d]\n", $textLength; printf " beforeDot: [%s]\n", $beforeDot; printf " afterDot: [%s]\n", $afterDot; printf " scientific: [%s]\n", $scientific; } my $spec; if ($afterDotLen <= 0) { # if the value is a float of some kind. Then it needs # to get rounded. $workingValue = Math::Round::round($value); # this is some kind of integer number. $spec = sprintf('%%0%d.%dd', $textLength, $textLength); } elsif ($scientificLen <= 0) { # this is a floating point number $spec = sprintf('%%0%d.%df', $textLength, $afterDotLen); } else { # this is a scientific number. $spec = sprintf('%%0%d.%dE', $textLength, $afterDotLen); } my $result = sprintf($spec, $workingValue); if($debug) { print " Original: [$value]\n"; print " Spec: [$spec]\n"; print "Working Value: [$workingValue]\n"; print " Result: [$result]\n\n"; } return $result; }