sub string_round { my $num = shift; my $pre = shift; my $dot = index($num, q{.}); my $_e_ = index($num, q{e}); if ( $[ <= $_e_ ) { my $exp = substr($num, $_e_+1); # Capture exp portion. $num = substr($num, 0, $_e_); # Remove the exp portion. if ( $[ > $dot ) { $dot = $_e_; # Has exp, no dot, set it to where the e was } else { # Remove the dot $num = ( substr($num, 0, $dot) . substr($num, $dot+1) ); } if (0!=$exp && ( -1 == ($exp/abs($exp)))) { # Negative exponent. # Numbers available (from $[ to $dot) # are within precison, after exponent is applied (exp - $dot) if ( (abs($exp)-$dot+$[) <= $pre ) { for ( my $cx = 0; $cx < abs($exp); $cx++ ) { $dot--; if ( $dot < $[ ) { $num = "0$num"; $dot++; } } } elsif ( abs($exp) > abs($dot-$pre+$[) ) { return 0; } else { for ( my $cx = 0; $cx < (abs($exp)-$dot+$[); $cx++ ) { $dot--; } } if ( $[ < $dot ) { $num = ( substr($num, 0, $[+$dot) . "." . substr($num, $[+$dot ) ); } else { $num = "0.$num"; $dot = $[ + 1; } } else { # Positive exponent. my $cx = 0; # Dot already removed from number # If $cx is less than exponent, walk along the number # (starting from where . was). for ( ; $cx < $exp; $cx++ ) { # If , somehow, $[ + $dot + $cx # ... is beyond the length of the string # cath up by adding more zeroes. while (( $[ + $dot + $cx ) >= length($num) ) { $num .= "0"; } } # Maybe I didn't add any zeroes. # $[ + $dot + $cx is still shorter then length # ... so, the number still has a dot, # and maybe still needs rounding. if (( $[ + $dot + $cx ) < (length($num)) ) { $dot = ( $dot + $exp ); $num = ( substr($num, 0, $[+$dot) . "." . substr($num, $[+$dot ) ); } else { # Already at end of string, just return the whole number. $dot = $[ - 1; return $num; } } } # End $_e_ ( exponent has been eliminated ) if ( $[ <= $dot ) { my $aPre = $[ + $dot + $pre; if ( length($num) >= $aPre ) { my $aCho = $aPre + 1; my $cho = substr($num, $aCho, 1); $num = substr($num, 0, $aCho); # Cut off num at expected length. if ( 5 <= $cho ) { SREV: for ( my $cx = $aPre; 0 <= $cx; $cx-- ) { my $noch = substr($num, $cx, 1); if (0==$cx) { if ( q{.} eq $noch) { $num = "1" . $num; } elsif ( q{9} eq $noch) { substr($num, $cx, 1) = "0"; $num = "1" . $num; } else { substr($num, $cx, 1) = ($noch + 1); } last SREV; } elsif ( q{.} eq $noch ) { next SREV; } elsif ( 9 != $noch ) { substr($num, $cx, 1) = ($noch + 1); last SREV; } else { substr($num, $cx, 1) = "0"; } } } } } return $num; }