I was going to clean this up this recent code of mine (a lot! It's ugly!!) before posting, but that'd be awhile to find the time (this is from last weekend), and you asked, so... Also, I hadn't yet searched through the code posted on PM - I really wonder if this hasn't been done better elsewhere. (Not in any CPAN modules that I can find, though)
I really wanted to handle quite large values, like some that are up into terabytes in just six months, and so I felt I needed to be able to handle large integers ala Math::BigInt. And I wanted to be able to handle the "K is 1000" vs. the "K is 1024" people. And I wanted to be able to reliably fit the output into a limited number of columns. Thus the following contortions...
# Convert bigint to printable number using KB, MB, GB as needed.
# Biggest string would be either 'NN.NXB' or 'NNNNXB' - 6 characters
+ long
sub ToScaledFormat {
my $bignum = Math::BigFloat->new( shift );
my $logbase = shift || 1000;;
my $scaling_lower_limit = 10000;
if( $bignum < $scaling_lower_limit ) {
return int($bignum);
}
my @sfx = ( '', qw( KB MB GB TB PB EB ZB YB ) );
my $log1000 = $bignum->copy->blog($logbase);
my $pow1000 = int($log1000);
my $wow = exp( ($log1000 - $pow1000) * log($logbase) );
# It is possible below to round up to our logbase value, which loo
+ks
# wrong! If we would, instead bump up to next power set
if( $wow >= ($logbase-0.5) ) {
$wow /= $logbase;
++$pow1000;
}
# If we are not using a decimal base, we may need to show 1023KB
# or such using four leading digits. Use an alternate format
if( $wow >= 1000 ) { # If four significant digits
return( sprintf("%.4g",$wow), $sfx[$pow1000] );
} else {
return( sprintf("%.3g",$wow), $sfx[$pow1000] );
}
}
--
I'm a pessimist about probabilities; I'm an optimist about possibilities.
Lewis Mumford