Как заставить bc печатать конечные нули?

Проблема связана с https://github.com/docker/docker/issues/8539, которая решена в докере 1.10 или более поздней версии. Была некоторая проблема с драйвером журнала Docker, которая привела к проблемам с буфером, особенно для сброса STDOUT контейнера.

4
07.01.2020, 22:03
4 ответа

Ваш вопрос немного двусмыслен. Вы говорите: «…Нужно сохранить все эти 0…». Другие рассказали вам, как получить вывод с восемью десятичными цифрами. Но хотите ли вы динамически определить, сколько десятичных цифр входные значения aи bуже имеют (, чтобы вы могли выводить cс той же точностью )?

Вы можете сделать это внутри bash:

a_digits=0
if [[ $a =~ \.([0-9]*)$ ]]
then
        a_digits="${#BASH_REMATCH[1]}"
fi
b_digits=0
if [[ $b =~ \.([0-9]*)$ ]]
then
        b_digits="${#BASH_REMATCH[1]}"
fi

=~сравнивает строку с регулярным выражением. Регулярное выражение \.([0-9]*)$соответствует.за которым следует последовательность цифр в конце строки, с последовательностью цифр в группе. BASH_REMATCH— это массив, содержащий совпадение для всего регулярного выражения. и группы захвата (, если таковые имеются ). Таким образом, если a – это 3.1416, BASH_REMATCH[1] – это 1416. Затем a_digitsполучает его длину, которая равна 4.

Если у вас нет bash, вы можете сделать то же самое командой expr:

a_digits=$( expr length '(' "$a" : '.*\.\([0-9]*\)$' ')' )
b_digits=$( expr length '(' "$b" : '.*\.\([0-9]*\)$' ')' )

что является точно такой же логикой.

Затем можно получить большее (максимальное )значение:

if [ "$a_digits" -gt "$b_digits" ]
then
        digits="$a_digits"
else
        digits="$b_digits"
fi

или наоборот, чтобы получить меньшее (минимальное )значение.

Затем вы можете использовать эту динамически определяемую точность в других решениях:

printf "%0.${digits}f\n" "$c"

или

printf '%0.*f\n' "$digits" "$c"

или

…scale=$digits; …
1
27.01.2020, 20:45

Просто используйте awk:

$ cat tst.sh
#!/bin/env bash

hypothenuse() {
    awk -v a="$1" -v b="$2" 'BEGIN {
        printf "This is a %0.8f and b %0.8f\n", a, b
        c = sqrt(a^2 + b^2)
        printf "This is c %0.8f\n", c
    }'
}

hypothenuse "$@"

$./tst.sh 0 0
This is a 0.00000000 and b 0.00000000
This is c 0.00000000

$./tst.sh 17.12 23.567
This is a 17.12000000 and b 23.56700000
This is c 29.12898709
3
27.01.2020, 20:45

Таким образом, вы можете внедрить форматирование, используяprintf:

printf "%0.8f" ${x}

Пример:

x=3
printf "%0.8f\n" ${x}
3.00000000

Примечание. Вывод:printfзависит от ваших региональных настроек.

7
27.01.2020, 20:45

В bc решение состоит в делении на 1:

$ bc -l <<<"scale=8; x=25*20; x"
500

$ bc -l <<<"scale=8; x=25*20; x/1"
500.00000000

Итак, ваш сценарий может быть таким:

hypothenuse () {
        local a b c x y
        a=${1}; b=${2}
        echo "This is a ${a} and b ${b}"
        x=$(echo "scale=8; $a^2/1" | bc -l)
        y=$(echo "scale=8; $b^2/1" | bc -l)
        echo "This is x ${x} and y ${y}"
#       local sum=`awk -v k=$x -v k=$y 'BEGIN {print (k + l)}'`
#       echo "This is sum ${sum}"
        c=$(echo "scale=8; sqrt($a^2 + $b^2)/1" | bc -l)
        echo "This is c ${c}"
}

Я настоятельно рекомендую вам использовать $(…)вместо `…`.

Но даже это не работает со значениями 0.

Лучшее решение состоит в том, чтобы масштаб bc был равен 20 (от bc -l ), выполнить всю необходимую математику одним вызовом bc, а затем отформатировать вывод в соответствии с требованиями с помощью printf. Да, printfможет форматировать числа с плавающей запятой.

Предполагая удар

hypothenuse () {  local a b c x y
                  a=${1:-0} b=${2:-0}
                  read -d '' x y c < <(
                  bc -l <<<"a=$a; b=$b; x=a^2; y=b^2; c=sqrt(x+y); x;y;c"
                  )

                  printf 'This is a %14.8f and b %14.8f\n' "$a" "$b"
                  printf 'This is x %14.8f and y %14.8f\n' "$x" "$y"
                  printf 'This is c %14.8f             \n' "$c"
               }
10
27.01.2020, 20:45

Теги

Похожие вопросы