Занимательная математика командной строки

Если вы пользователь Linux, Free/Open BSD или другой свободной ОС, есть вероятность, что интерфейс командной строки вам не чужд. В таком случае можно использовать командную оболочку для простых арифметических действий. Для этого не нужно устанавливать дополнительных программ, все уже есть в базовом наборе операционной системы. Они позволяют качественно заменить привычный калькулятор на столике счетовода.


ac3022f59856451dac8325c527c54a70.png

bash калькулятор целочисленный


Арифметические операции с целочисленными в bash будут выглядеть так:


$((expression))
$(( n1+n2 ))
$(( n1/n2 ))
$(( n1*n2 ))
$(( n1-n2 ))

Например:


$ echo $((15+25))
$ 40

На man странице bash, в разделе ARITHMETIC EVALUATION вы можете ознакомиться с приоритетом исполнения действий операторов

И, кстати, можно получить тот же результат, используя команду expr целочисленное выражение, вместо подстановки с двойными скобками в командах вывода.


$ expr 15+25
$ 40

bc мэдскиллз


Целочисленные выражения это конечно хорошо, но как-то маловато даже для калькулятора. Благо в наборе есть еще bc — Си-подобный интерактивный интерпретатор. Не будем тратить время на сложение и вычитание, перейдем сразу к более интересным занятиям.


$ echo 7^7 |bc
823543

Это уже получше калькулятора, так как позволяет получить любое количество чисел в дробной части с помощью переменной scale. Остерегайтесь поддельных проприетарных версий bc, так как они поддерживают всего-лишь 99 знаков после запятой!


$ echo 'scale=30;sqrt(2)' | bc
1.414213562373095048801688724209

Еще 2 важные переменные: ibase и obase указывают на основание входящих и исходящих чисел.


$ echo 'ibase=16;obase=A;FF' | bc
255

Тут, кстати, есть засада. Посмотрите на эти два примера. Вроде бы пытаешься сделать то же самое, но результат разный. Вся суть в том, что в первом примере ibase=2, но сама obase=10 принимает значение 2 в силу того, что ibase определяет по базе obase и 10 становится равной 2. Чтобы разорвать этот круг, надо использовать hex.


$ echo 'ibase=2;obase=10;10' | bc
10
$ echo 'ibase=2;obase=A;10' | bc
2

При множественном возведении числа в степень важно расставить нужным образом скобки, а то программа сама решит как лучше группировать.


$ echo '4^4^4' |bc
13407807929942597099574024998205846127479365820592393377723561443721\
76403007354697680187429816690342769003185818648605085375388281194656\
9946433649006084096
$ echo '(4^4)^4' |bc
4294967296

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


$ bc -q
4^4^4
13407807929942597099574024998205846127479365820592393377723561443721\
76403007354697680187429816690342769003185818648605085375388281194656\
9946433649006084096
quit

Замер производительности процессора с bc


Много лун назад на одном популярном англоязычном форуме, ныне покойном, предложили гениально простой способ нагреть проц и посчитать его скорость в попугаях.


time echo "scale=5000; 4*a(1)" | bc -l -q

Мы подгружаем в bc математическую библиотеку опцией -l и просим выдать число π с точностью 5000 знаков после запятой. Мой результат вычисления на Intel(R) Core(TM) i5-4300U CPU @ 1.90GHz:


real    0m24.507s
user    0m24.490s
sys     0m0.000s

Подгружаемые математические функции
s (x) The sine of x, x is in radians.
c (x) The cosine of x, x is in radians.
a (x) The arctangent of x, arctangent returns radians.
l (x) The natural logarithm of x.
e (x) The exponential function of raising e to the value x.
j (n,x) The Bessel function of integer order n of x.

Скрипты bc


В bc можно, если очень нужно, определять функции и запускать скрипты. Определение функции имеет следующий синтаксис:


define name ( parameters ) { newline
    auto_list statement_list }

Определены условные операторы if и else, причем последний не обязательно использовать, а также заголовки цикла for и while. На Википедии можно просмотреть список математических операторов и сравнить с таковым в Си. А вот так выглядит расчет чисел Фибоначчи в bc.


#!/usr/bin/bc -q
define fibo(n) {
    if (x <= 2) return n;
    a = 0;
    b = 1;
    for (i = 1; i < n; i++) {
        c = a+b; a = b; b = c;
    }
    return c;
}
fibo(1000)
quit

Как ЯП bc не взлетел, однако в качестве настольного калькулятора он более чем хорош.


awk: арифмометр и гадалка


Мне не часто доводилось пользоваться awk, поэтому каждый раз я с удивлением обнаруживаю новые возможности этой программы. Если нужно посчитать логарифмы или синусы, не спешите паниковать, man awk вам поможет. Вот так мы получили квадратный корень.


awk 'BEGIN{print sqrt(196)}'
14

А вот мы уже логарифмируем число π, 5000 знаков которого мы уже вычисляли с помощью bc.


awk 'BEGIN{print log(3.141592653589793238462643383279502884197169399375105820974944592307)}'
1.14473

Оглашаю полный список возможностей


atan2(y, x)   Return the arctangent of y/x in radians.
cos(expr)     Return the cosine of expr, which is in radians.
exp(expr)     The exponential function.
int(expr)     Truncate to integer.
log(expr)     The natural logarithm function.
rand()        Return a random number N, between 0 and 1, such that 0 ≤ N < 1.
sin(expr)     Return the sine of expr, which is in radians.
sqrt(expr)    Return the square root of expr.
srand([expr]) Use expr as the new seed for the random number generator.  If no expr is provided, use the time of day. Return the previous seed for the random number generator.

Иногда, хочется довериться судьбе и послать все на три буквы — awk. Вообще-то, это пример из книги издательства O’Reilly, имитирует бросание монетки, выдавая 2 разных события пить или не пить с одинаковой вероятностью.


#!/bin/bash
ans=`awk -vmin=0 -vmax=1 'BEGIN{srand(); print int(min+rand()*(max-min+1))}'`

if [ $ans -eq 0 ]; then
    echo "no"
else
    echo "yes"
fi

В заключение


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


I. Замена калькулятора


  1. Встроенные средства командной оболочки: арифметические подстановки bash.
  2. Программа GNU bc.
  3. Неформат — awk.

II. Таблицы


  1. OpenOffice / LibreOffice Calc.
  2. KDE KSpread.
  3. GNOME Gnumeric.
  4. Одиночные, например: GNU Oleo и другие.

III. Специализированные математические программы, уровень студент+


  1. GNU Ocatve.
  2. Scilab.
  3. Maxima.
  4. R.
  5. Sage.

IV. Языки программирования, математические библиотеки и среды


  1. Ansi C, библиотеки math.h, complex.h, GSL и другие товарищи.
  2. Java Scientific Library
  3. Python, библиотеки SciPy, NumPy, Sympy и другие товарищи.
  4. COBOL.
  5. Fortran.
  6. Intel Math Kernel Library (Intel MKL)
  7. AMD Accelerated Parallel Processing Math (APPLM)
  8. AMD Core Math Library (ACML)

Список, естественно не полный, поэтому заранее прошу прощение, если не указал чей-то излюбленный математический пакет или ЯП. Последняя группа — поистине разливанное море разнообразного и годного софта.


А вот и обещанный мэдскиллз вместе с ответом на вопрос из картинки. Источник.


diff -u <(seq -f '%03.0f' 0 999) <((bc <<<'scale = 3009; 1 / 998001' | tr -d '\\\n'; echo) | sed s/.// | fold -3)

Комментарии (2)

  • 24 сентября 2016 в 05:34

    0

    Бенчмарк на i7–5775c, линукс в виртуалбоксе на винде.

    real 0m19.454s
    user 0m19.420s
    sys 0m0.000s

    Антиоффтопик:
    То есть, bc позволяет оперировать только от 2 до 16-ричной системы?
    А есть простой способ переводить в произвольную систему, без программирования?

  • 24 сентября 2016 в 06:37 (комментарий был изменён)

    0

    real 0m19.366s
    user 0m19.337s
    sys 0m0.024s
    mbpro
    MacBook Pro, i7 2.7 GHz, 16 Gb 1600 MHz DDR3

    Но как бенчмарк не интересно: грузилось только 1 и 8 ядер

© Habrahabr.ru