Perl - удалить конечные нули без экспоненциального значения - PullRequest
4 голосов
/ 30 декабря 2011

Я пытаюсь удалить конечные нули из десятичных чисел.

Например: если входное число равно 0,0002340000, я хотел бы, чтобы выходное значение было 0,000234

Я использую sprintf("%g",$number), но это работает по большей части, за исключением того, что иногда оно преобразует число в экспоненциальное значение с E-.Как сделать так, чтобы оно отображалось только как полное десятичное число?

Ответы [ 6 ]

3 голосов
/ 30 декабря 2011

Числа не имеют конечных нулей.Замыкающие нули могут появляться только после того, как вы представляете число в десятичном виде, строку.Поэтому первым шагом является преобразование числа в строку, если это еще не сделано.

my $s = sprintf("%.10f", $n);

(Решение состоит в том, чтобы работать с входами ОП, а его входы имеют 10 десятичных знаков. Если вычтобы появилось больше цифр, используйте число десятичных разрядов, которое вы хотите отобразить, вместо 10. Я подумал, что это очевидно. Если вы хотите быть смешным, как @asjo, используйте 324 десятичных знака для двойных, если вы хотите, чтобы непотерять любую точность, которую вы еще не потеряли.)

Затем вы можете удалить конечные нули.

$s =~ s/0+\z// if $s =~ /\./;
$s =~ s/\.\z//;

или

$s =~ s/\..*?\K0+\z//;
$s =~ s/\.\z//;

или

$s =~ s/\.(?:|.*[^0]\K)0*\z//;
1 голос
/ 30 декабря 2011

Ленивый путь может быть простым: $number=~s/0+$// (заменять конечные нули ничем).

1 голос
/ 30 декабря 2011

Решение проще, чем вы думаете.

Вместо использования %g используйте %f, и это приведет к поведению, которое вы ищете. %f всегда будет выводить ваше плавающее десятичное число в " фиксированной десятичной записи ".


Что говорится в документации %g против %f?

Как вы можете заметить в приведенной ниже таблице, %g приведет к тому же значению, что и %f или %e (при необходимости).

Если вы хотите принудительно использовать фиксированную десятичную запись используйте соответствующий идентификатор формата, который в данном случае равен %f.

sprintf - perldoc.perl.org

   %%    a percent sign
   %c    a character with the given number
   %s    a string
   %d    a signed integer, in decimal
   %u    an unsigned integer, in decimal
   %o    an unsigned integer, in octal
   %x    an unsigned integer, in hexadecimal
   %e    a floating-point number, in scientific notation
   %f    a floating-point number, in fixed decimal notation
   %g    a floating-point number, in %e or %f notation

А как насчет TIMTOWTDI; Разве мы не пишем Perl?

Да, как всегда, есть несколько способов сделать это.

Если вы просто хотите обрезать завершающие нули десятичной точки из строки , вы можете использовать регулярное выражение, например ниже.

$number =  "123000.321000";
$number =~ s/(\.\d+?)0+$/$1/;

$number # is now "12300.321"

Помните, что значения с плавающей точкой в ​​perl не имеют конечных десятичных дробей, если только вы не имеете дело со строкой. С этим сказал; строка не является числом, даже если она может быть явно и неявно преобразована в единицу.

1 голос
/ 30 декабря 2011

Чтобы избежать научного обозначения чисел, используйте преобразование формата %f вместо %g.

0 голосов
/ 30 декабря 2011

Простой способ:

Вы могли бы немного обмануть.Добавьте 1, чтобы избежать взлома числа в научной нотации.Затем манипулируйте числом как строкой (таким образом, Perl преобразует его в строку).

$n++; 
$n =~ s/^(\d+)(?=\.)/$1 - 1/e;
print $n;

«Правильный» способ:

Дляболее «правильное» решение, подсчет количества десятичных знаков для использования с %f будет оптимальным.Оказалось, что получить правильное количество десятичных знаков сложнее, чем можно подумать.Вот попытка:

use strict;
use warnings;
use v5.10;

my $n = 0.000000234;
say    "Original: $n";
my $l = getlen($n);
printf "New     : %.${l}f\n", $n;

sub getlen {
    my $num = shift;
    my $dec = 0;
    return 0 unless $num;    # no 0 values allowed
    return 0 if $num >= 1;   # values above 1 don't need this computation
    while ($num < 1) {
        $num *= 10;
        $dec++;
    }
    $num =~ s/\d+\.?//;     # must have \.? to accommodate e.g. 0.01
    $dec += length $num;
    return $dec;
}

Вывод:

Original: 2.34e-007
New     : 0.000000234
0 голосов
/ 30 декабря 2011

Весь смысл формата %g состоит в том, чтобы использовать запись с фиксированной точкой, когда это целесообразно, и использовать экспоненциальную запись, когда фиксированная точка не является разумной. Итак, вам нужно знать диапазон значений, с которыми вы будете иметь дело.

Очевидно, что вы могли бы написать регулярное выражение для постобработки строки из sprintf(), удалив завершающие нули:

my $str = sprintf("%g", $number);
$str =~ s/0+$//;

Если вам всегда нужен номер с фиксированной точкой, используйте '%f', возможно, с нужным вам количеством десятичных знаков; Вам все еще может понадобиться удалить конечные нули. Если вам всегда нужна экспоненциальная запись, используйте '%e'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...