use strict; #use warnings; # sprintf doesn't like nulls as values my %test = ( '' => 0, '.5' => 0, 1 => 0, '3.' => 0, 100 => 4, 12.4 => 1, 12.56 => 0, 12.45435 => 0, 123.45678 => 3, 3.14 => 5, 1 => 5, 10 => 5, 100 => 5, 1000 => 5, ); printf('value|precision'."%12s"x4 ."\n", qw(sprintf Incognito Albannach jeffa)); while (my ($v,$p)= each %test) { printf("%14s:","'$v'|$p"); printf("%12s"x4 ."\n", sprintf("%.${p}f", $v), Incognito($v,$p), Albannach($v,$p), jeffa($v,$p) ); } sub Albannach { my($val, $pre) = @_; $val =~ s/(\d*)(\.?)(\d*)/"$1".($pre?'.':'').substr($3.'0'x$pre, 0, $pre)/e; $val; } sub Incognito { my ($strValue,$strPrecision) = @_; # Pad the number with a bunch of zeros $strValue =~ s/^(\d*)\.?(\d*)$/${1}.${2}000000000/; # Remove all but the first '$strPrecision' digits that immediately # trail the decimal point. my $strDefaultPrecision = 2; $strPrecision = ($strPrecision >= 0) ? $strPrecision : $strDefaultPrecision; if ($strPrecision == 0) { $strValue =~ s/^(\d*)\.?\d*$/$1/; } else { $strValue =~ s/^(\d*\.\d{$strPrecision})\d*$/$1/; } $strValue; } sub jeffa { my ($str,$pad) = @_; my ($add,$right); ($str,$right) = split('\.',$str,2); $right = ($right) ? ".$right" : ''; $add = $pad - length($str); return $str if $add < 1; return ('0' x $add) . $str . $right; }