Искусство программирования на языке сценариев командной оболочки
Шрифт:
#+ то отношение попаданий в воду к общему числу выстрелов будет примерно равно
#+ значению PI/4.
#
# По той простой причине, что стрельба фактически ведется только
#+ по правому верхнему квадранту карты.
# (Предыдущее описание было несколько упрощено.)
#
# Теоретически, чем больше будет произведено
# Однако, сценарий на языке командной оболочки, в отличие от других языков программирования,
#+ в которых доступны операции с плавающей запятой, имеет некоторые ограничения.
# К сожалению, это делает вычисления менее точными.
DIMENSION=10000 # Длина стороны квадратного участка поверхности.
# Он же -- верхний предел для генератора случайных чисел.
MAXSHOTS=1000 # Количество выстрелов.
# 10000 выстрелов (или больше) даст лучший результат,
# но потребует значительного количества времени.
PMULTIPLIER=4.0 # Масштабирующий коэффициент.
get_random
{
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')
RANDOM=$SEED # Из примера "seeding-random.sh"
let "rnum = $RANDOM % $DIMENSION" # Число не более чем 10000.
echo $rnum
}
distance= # Объявление глобальной переменной.
hypotenuse # Расчет гипотенузы прямоугольного треугольника.
{ # Из примера "alt-bc.sh".
distance=$(bc -l << EOF
scale = 0
sqrt ( $1 * $1 + $2 * $2 )
EOF
)
# Установка "scale" в ноль приводит к округлению результата "вниз",
#+ это и есть то самое ограничение, накладываемое командной оболочкой.
# Что, к сожалению, снижает точность аппроксимации.
}
# main {
# Инициализация переменных.
shots=0
splashes=0
thuds=0
Pi=0
while [ "$shots" -lt "$MAXSHOTS" ] #
do
xCoord=$(get_random) # Получить случайные координаты X и Y.
yCoord=$(get_random)
hypotenuse $xCoord $yCoord # Гипотенуза = расстоянию.
((shots++))
printf "#%4d " $shots
printf "Xc = %4d " $xCoord
printf "Yc = %4d " $yCoord
printf "Distance = %5d " $distance # Растояние от
#+ центра озера,
#+ с координатами (0,0).
if [ "$distance" -le "$DIMENSION" ]
then
echo -n "ШЛЕП! " # попадание в озеро
((splashes++))
else
echo -n "БУХ! " # попадание на твердую почву
((thuds++))
fi
Pi=$(echo "scale=9; $PMULTIPLIER*$splashes/$shots" | bc)
# Умножение на коэффициент 4.0.
echo -n "PI ~ $Pi"
echo
done
echo
echo "После $shots выстрела, примерное значение числа \"пи\" равно $Pi."
# Имеет тенденцию к завышению...
# Вероятно из-за ошибок округления и несовершенства генератора случайных чисел.
echo
# }
exit 0
# Самое время задуматься над тем, является ли сценарий удобным средством
#+ для выполнения большого количества столь сложных вычислений.
#
# Тем не менее, этот пример может расцениваться как
# 1) Доказательство возможностей языка командной оболочки.
# 2) Прототип для "обкатки" алгоритма перед тем как перенести
#+ его на высокоуровневые языки программирования компилирующего типа.