How to move the decimal point N places to the left efficiently?

This is a bit verbose, but should do the trick:

sub move_point {
    my ($n, $places) = @_;

    die 'negative number of places' if $places < 0;
    return $n if $places == 0;

    my ($i, $f) = split /\./, $n;  # split to integer/fractional parts

    $places += length($f);

    $n = sprintf "%0*s", $places+1, $i.$f;  # left pad with enough zeroes
    substr($n, -$places, 0, '.');  # insert the decimal point
    return $n;
}

Demo:

my $n = "12.34";

for my $p (0..5) {
    printf "%d  %s\n", $p, move_point($n, $p);
} 

0  12.34
1  1.234
2  0.1234
3  0.01234
4  0.001234
5  0.0001234