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



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

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


$ echo '4^4^4' |bc
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
$ echo '(4^4)^4' |bc
4294967296

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


$ bc -q
4^4^4
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
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)
Поделиться с друзьями
-->

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


  1. saboteur_kiev
    24.09.2016 05:34
    +1

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

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

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


    1. vlin
      24.09.2016 12:03

      i5-4460 CPU @ 3.20GHz, ESXi 6, тест в двух виртуалках — Linux и FreeBSD
      Примерно двукратная разница, результат расчета одинаков.
      Наверное разные реализации bс, не думаю что от ОС так зависит.

      Debian 8.2:

      real 0m17.874s
      user 0m17.796s
      sys 0m0.000s

      FreeBSD 10.3-RELEASE:

      9.600u 0.047s 0:09.67 99.6% 40+167k 0+0io 0pf+0w


    1. Danov
      24.09.2016 15:09

      i7-4700, встроенный в Win10 Bash
      real 0m15.492s
      user 0m15.438s
      sys 0m0.016s


      1. Danov
        24.09.2016 15:14

        уточню:
        i7-4770 CPU @ 3.40GHz и загрузка лишь +14%.
        Точно не про «нагреть проц»


        1. G-M-A-X
          24.09.2016 22:45

          Скорее всего, данный код однопоточный.
          Запустите несколько потоков.


    1. gromozeka1980
      24.09.2016 18:36
      +1

      А есть простой способ переводить в произвольную систему, без программирования?
      Есть. Делим с остатком на основание системы. Остаток записываем справа. С результатом повторяем операцию, пока число не кончится.

      19 в двоичной
      19/2=9, остаток 1
      9/2=4, остаток 1
      4/2 = 2, остаток 0
      2/2 =1, остаток 0
      1/2 = 0, остаток 1
      записываем это всё справа-налево — 10011

      19 в пятиричной
      19/5 = 3, остаток 4
      3/5 = 0, остаток 3
      записываем справа-налево — 34

      19 в 19-ричной
      19/19 = 1, остаток 0
      1/19 = 0, остаток 1
      записываем справа-налево — 10

      19 в любой системе с основанием больше 19
      19/Основание = 0, остаток 19
      считаем 19 буквами, (помним, что F — 15) получаем J


      1. saboteur_kiev
        24.09.2016 19:31

        Это не совсем простой, я думал что-то типа
        echo «base=10; 12312313» | bc
        Но без ограничений.
        А тут все равно придется писать.


        1. gromozeka1980
          24.09.2016 19:36

          а, я протупил. я решил, что вы спрашиваете, как вручную переводить в любую систему :)


        1. gromozeka1980
          24.09.2016 19:37

          https://www.tools4noobs.com/online_tools/base_convert/


    1. ZyXI
      24.09.2016 19:31
      +3

      Zsh позволяет использовать любую систему счисления с целочисленными основаниями от 2 до 36:


      % echo $(( [#36] 15#1078ABE ))
      36#70D7H

      Специально для 16?ричной системы работает префикс 0x, для двоичной — 0b, других специальных префиксов нет (для 8?ричной можно включить обычный 0755 == 493, но по?умолчанию это отключено). Zsh также работает и с числами с плавающей точкой (но только в десятичной записи). Но zsh работает только с 64?битными целыми и double, никакой длинной арифметики или чисел произвольной точности. Можно попросить zsh отделять каждые n разрядов, по?умолчанию 3:


      % echo $(( [#_] 107825.17632 ))
      107_825.176_32
      % echo $(( [#_4] 107825.17632 ))
      10_7825.1763_2


  1. LeonidZ
    24.09.2016 06:37

    real 0m19.366s
    user 0m19.337s
    sys 0m0.024s

    mbpro
    MacBook Pro, i7 2.7 GHz, 16 Gb 1600 MHz DDR3

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


  1. warlock13
    24.09.2016 09:38
    +1

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

    Чушь. Программа ничего не группирует, она просто делает то, что вы скажете. В следующем примере вы приказываете ей посчитать image4^4^4, и она так и делает.


    1. ZyXI
      24.09.2016 19:43
      -1

      В программе забит приоритет и ассоциативность операторов, что превращает 4^4^4 в 4^(4^4). Такое вполне правильно считать «группировкой».


      1. warlock13
        24.09.2016 20:09
        +3

        А ещё в программу заложены правила записи числ цифрами и сложения чисел. Значит ли это, что при сложении чисел важно правильно записать исходные числа (ну скажем, не вводить 3+3, если хочешь сложить 2 и 2), а то программа сама решит как лучше складывать числа?


        1. ZyXI
          24.09.2016 20:54

          Во всех случаях программа «сама решает» в соответствии с заложенными в неё правилами. Я отвечал на ваше «ничего не группирует» — ассоциативность операторов определяет группировку и говорить так не менее некорректно.


  1. surefire
    24.09.2016 10:01
    +1

    Из консоли считаю в node, просто запускаю и пишу выражение.
    В gnome3 при установленном калькуляторе, можно считать прямо в строке поиска приложений.


    1. AllexIn
      24.09.2016 10:41
      +2

      И в KDE тоже.


      1. temujin
        24.09.2016 15:02

        В Плазме или 4-й версии?


        1. IgorV
          24.09.2016 18:25

          В 4-й точно считает, в строке которая по Alt+F2 вызывается. Очень удобно, не знал до этого и всегда в консоли считал :)


    1. Zibx
      24.09.2016 18:49

      Во время чтения интернета для этой цели удобно использовать F12.


  1. Aineko
    24.09.2016 10:05

    real 0m23.759s
    user 0m23.547s
    sys 0m0.016s
    i5-2410M 2.30GHz
    ubuntu bash on windows


  1. Ktulhy
    24.09.2016 10:33
    +5

    ipython в этом плане, наверное, лучше)


    1. 0xd34df00d
      24.09.2016 19:02

      О, а я ghci использую.


  1. athost
    24.09.2016 11:05
    +1

    >$ expr 15+25

    Пробелы пропущены, должно быть

    $ expr 15 + 25


    1. temujin
      24.09.2016 11:10

      Вы правы, сейчас исправлю.

      $ expr 15+25
      $ 15+25


  1. leremin
    24.09.2016 12:24
    +3

    Я в Windows вместо калькулятора использую python из командной строки


  1. janatem
    24.09.2016 13:33
    +2

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

    Из общих соображений кажется естественным вначале задавать obase в привычной системе, потом ibase. Я так попробовал, и оно работает ожидаемым образом:


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


    1. temujin
      24.09.2016 23:42

      Класс!

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


      1. janatem
        25.09.2016 01:31

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


        ibase=2;obase=10;

        — здесь мне тоже хочется увидеть такой смысл:


        (ibase,obase)=(2,10)

        но в тех присваиваниях притаился побочный эффект.


  1. xenohunter
    24.09.2016 14:20

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

    В Arch по умолчанию нет bc.


    1. A-Stahl
      24.09.2016 15:15
      -1

      Это происки злой математички из 8-«Б» чтобы дети устно учились считать…


    1. ValdikSS
      24.09.2016 20:26
      +1

      Да и в Debian тоже.


  1. Riateche
    24.09.2016 17:57
    -1

    Еще существует консольный калькулятор apcalc.


  1. naething
    24.09.2016 23:37
    +1

    Единственное, что в bc раздражает, — это скудность математической библиотеки. Например, возведение в дробную степень отсутствует:
    $ echo '2^1.5' | bc -l
    Runtime warning (func=(main), adr=9): non-zero scale in exponent
    2

    Приходится извращаться с помощью экспоненты и логарифма, что не очень удобно:
    $ echo 'e(l(2)*1.5)' | bc -l
    2.82842712474619009755

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


  1. neit_kas
    25.09.2016 06:01

    Виндовый CMD (а если точнее batch) тоже немного могёт в расчёты. Имеются: сложение, вычитание, умножение и деление (целочисленное, остаток подавляется). Например:
    set /a result=15+25
    echo %result%
    Стоит отметить, если не в скриптах пилить, то результат выдаст и первая строчка. Кроме того, учитывая тот факт, что приличная часть народу на линуксах использует wine, то сей метод хоть и бессмыслен, но всё же имеет место быть.


  1. Sabbaot
    25.09.2016 19:29

    про bc рассказывается в книге «UNIX and Linux System Administration Handbook, 4th Edition» в вводной про сети. там же — про ipcalc, для расчета сетевых адресов и масок подсетей.
    про GHCi выше уже сказали, познакомился, когда пытался в haskell
    насчет таблиц и графиков, пользуем SigmaPlot


  1. KawaiDesu
    26.09.2016 14:54
    +1

    Использую calc (пакет в Ubuntu — apcalc, в Arch — calc). В отличии от bc имеет более очевидный синтаксис и терпим к нему (не нужно следить за пробелами между частами выражения, «25+ 4 -6» = 23), фактически может использоваться как скриптовой язык (!) через #!/usr/bin/calc. Жаль, его нет в дефолтной поставке.
    А в раздел «математические среды», возможно, стоит добавить RStudio.


  1. potan
    26.09.2016 15:27
    -1

    В PowerShell арифметика в естественном виде доступна сразу. Я очень рад, что он портирован под Linux, очень удобно.
    Сам все еще часто пользуюсь bc или ghci (когда надо что-то нетривиальное со строками или списками посчитать), реже awk, если попалась какая-то таблица, а дочку пытаюсь приучить к R (она сопротивляется и пользуется обычным микрокалькулятором, даже не программируемым).


  1. catharsis
    27.09.2016 16:16
    +1

    Пример с потерей числа интересный, спасибо.
    Понадобилось какое-то время, чтобы понять, о чём речь и что к чему, особенно если пропустить ссылку на «источник» :)