Como fazer cálculos com números inteiros e flutuantes, no bash ou em outros idiomas / frameworks?

255

Usar echo "20+5" literalmente produz o texto " 20+5 ".

Qual comando posso usar para obter a soma numérica, 25 neste caso?

Além disso, qual é a maneira mais fácil de fazer isso usando apenas o bash para ponto? Por exemplo, echo $((3224/3807.0)) imprime 0 : (.

Estou procurando respostas usando o shell de comando básico ('comando line ') em si ou através da utilização de linguagens disponíveis a partir do linha de comando.

    
por Michael Durrant 14.06.2012 / 16:43

16 respostas

347

Existem muitas opções !!!

Resumo

$ printf %.10f\n "$((10**9 * 20/7))e-9"   # many shells. Not mksh.
$ echo "$((20.0/7))"                       # (ksh93/zsh/yash, not bash)
$ awk "BEGIN {print (20+5)/2}"
$ zcalc
$ bc <<< 20+5/2
$ bc <<< "scale=4; (20+5)/2"
$ dc <<< "4 k 20 5 + 2 / p"
$ expr 20 + 5
$ calc 2 + 4
$ node -pe 20+5/2  # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI
$ echo 20 5 2 / + p | dc 
$ echo 4 k 20 5 2 / + p | dc 
$ perl -E "say 20+5/2"
$ python -c "print 20+5/2"
$ python -c "print 20+5/2.0"
$ clisp -x "(+ 2 2)"
$ lua -e "print(20+5/2)"
$ php -r 'echo 20+5/2;'
$ ruby -e 'p 20+5/2'
$ ruby -e 'p 20+5/2.0'
$ guile -c '(display (+ 20 (/ 5 2)))'
$ guile -c '(display (+ 20 (/ 5 2.0)))'
$ slsh -e 'printf("%f",20+5/2)'
$ slsh -e 'printf("%f",20+5/2.0)'
$ tclsh <<< 'puts [expr 20+5/2]'
$ tclsh <<< 'puts [expr 20+5/2.0]'
$ sqlite3 <<< 'select 20+5/2;'
$ sqlite3 <<< 'select 20+5/2.0;'
$ echo 'select 1 + 1;' | sqlite3 
$ psql -tAc 'select 1+1'
$ R -q -e 'print(sd(rnorm(1000)))'
$ r -e 'cat(pi^2, "\n")'
$ r -e 'print(sum(1:100))'
$ smjs
$ jspl

Detalhes

Shells

Você pode usar a expansão aritmética POSIX para número inteiro aritmética echo "$((...))" :

$ echo "$((20+5))"
25
$ echo "$((20+5/2))"
22

Bastante portátil ( ash dash yash bash ksh93 lksh zsh ):
Usando a habilidade printf para imprimir floats, podemos estender a maioria das shells para fazer matemática de ponto flutuante, embora com um alcance limitado (não mais de 10 dígitos):

$ printf %.10f\n "$((1000000000 *   20/7  ))e-9"
2.8571428570

ksh93 , yash e zsh são compatíveis com flutuadores aqui:

$ echo "$((1.2 / 3))"
0.4

somente ksh93 (diretamente) e zsh carregando a biblioteca mathfunc aqui:

$ echo "$((4*atan(1)))"
3.14159265358979324

( zsh precisa carregar zmodload zsh/mathfunc para obter funções como atan ).

Interativamente com zsh:

$ autoload zcalc
$ zcalc
1> PI/2
1.5708
2> cos($1)
6.12323e-17
3> :sci 12
6.12323399574e-17

Com (t) csh (apenas inteiro):

% @ a=25 / 3; echo $a
8

Na família de rc , akanga é aquele com expansão aritmética:

; echo $:25/3
8

Toolix de POSIX

bc (veja abaixo para o modo interativo), manual aqui

Mnemônico: b est c calculador (embora o b seja de fato para básico ).

$ echo 20+5/2 | bc
22
$ echo 'scale=4;20+5/2' | bc
22.5000

(suporta números de precisão arbitrária)

modo interativo bc:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'. 
5+5
10

2.2+3.3
5.5

A solução do Rush , expr (sem modo interativo):

$ expr 20 + 5
25
$ expr 20 + 5 / 2
22

A solução de Joshua : awk (sem modo interativo):

$ calc() { awk "BEGIN{print $*}"; }
$ calc 1/3
0.333333

Outras ferramentas mais ou menos portáteis

Solução do Arcege , dc (modo interativo: dc ):

O que é ainda mais divertido, pois funciona com a notação de polimento inverso.

$ echo 20 5 2 / + p | dc 
22
$ echo 4 k 20 5 2 / + p | dc 
22.5000

Mas não é tão prático a menos que você trabalhe muito com a notação de polimento inverso.

Observe que dc é anterior a bc e bc foi implementado historicamente como um wrapper em torno de dc , mas dc não foi padronizado por POSIX

DQdims ' calc (obrigatório sudo apt-get install apcalc) :

$ calc 2 + 4
6

Intérpretes de idioma de propósito geral:

solução do manatwork , node (modo interativo: node ; função de saída não necessária):

$ node -pe 20+5/2  # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI
22.5

Perl (modo interativo: perl -de 1 ):

$ perl -E "say 20+5/2"
22.5

Python (modo interativo: python ; função de saída não é necessária):

$ python -c "print(20+5/2)"
22 # 22.5 with python3
$ python -c "print(20+5/2.0)"
22.5

Também suporta números de precisão arbitrária:

$ python -c 'print(2**1234)'
295811224608098629060044695716103590786339687135372992239556207050657350796238924261053837248378050186443647759070955993120820899330381760937027212482840944941362110665443775183495726811929203861182015218323892077355983393191208928867652655993602487903113708549402668624521100611794270340232766099317098048887493809023127398253860618772619035009883272941129544640111837184

Se você tiver clisp instalado, também poderá usar a notação polonesa:

$ clisp -x "(+ 2 2)"

A solução do Marco , lua (modo interativo: lua ):

$ lua -e "print(20+5/2)"
22.5

PHP (modo interativo: php -a ):

$ php -r 'echo 20+5/2;'
22.5

Ruby (modo interativo: irb ; função de saída não necessária):

$ ruby -e 'p 20+5/2'
22
$ ruby -e 'p 20+5/2.0'
22.5

Guile (modo interativo: guile ):

$ guile -c '(display (+ 20 (/ 5 2)))'
45/2
$ guile -c '(display (+ 20 (/ 5 2.0)))'
22.5

S-Lang (modo interativo: slsh ; função de saída não necessária, apenas um ; terminator):

$ slsh -e 'printf("%f",20+5/2)'
22.000000
$ slsh -e 'printf("%f",20+5/2.0)'
22.500000

Tcl (modo interativo: tclsh ; função de saída não é necessária, mas expr é):

$ tclsh <<< 'puts [expr 20+5/2]'
22
$ tclsh <<< 'puts [expr 20+5/2.0]'
22.5

Javascript shells:

$ smjs
js> 25/3
8.333333333333334
js>

$ jspl
JSC: 25/3

RP: 8.33333333333333
RJS: [object Number]
JSC:
Good bye...

$ node
> 25/3
8.333333333333334
>

Vários SQL's:

SQLite (modo interativo: sqlite3 ):

$ sqlite3 <<< 'select 20+5/2;'
22
$ sqlite3 <<< 'select 20+5/2.0;'
22.5

MySQL :

mysql -BNe 'select 1+1'

PostgreSQL :

psql -tAc 'select 1+1

_As opções no mysql e postgres param a imagem 'ascii art'!

Idiomas orientados para matemática especializados:

R no modo simples - permite gerar 1000 números aleatórios normais e obter o desvio padrão e imprimi-lo

$ R -q -e 'print(sd(rnorm(1000)))'
> print(sd(rnorm(1000)))
[1] 1.031997

R usando o script littler - vamos imprimir pi ao quadrado

$ r -e 'cat(pi^2, "\n")'
9.869604
$  r -e 'print(sum(1:100))'
[1] 5050

PARI / GP , um extenso sistema de álgebra computacional para teoria dos números, álgebra linear e muitas outras coisas

$ echo "prime(1000)"|gp -q
7919                        // the 1000th prime
$ echo "factor(1000)" | gp -q
[2 3]
[5 3]                       // 2^3*5^3
$ echo "sum(x=1,5,x)" | gp -q
15                          // 1+2+3+4+5

GNU Octave (uma linguagem interpretada de alto nível, destinada principalmente a cálculos numéricos)

Também suporta números complexos:

$ octave
>> 1.2 / 7
ans =  0.17143
>> sqrt(-1)
ans =  0 + 1i

Julia , linguagem de alto desempenho e intérprete para computação científica e numérica.

Opção não interativa:

$ julia -E '2.5+3.7'
6.2
    
por 13.09.2018 / 17:39
33

Existem várias maneiras de calcular. Para expressões simples, você pode usar o bash :

echo $((20+5))

ou expr :

expr 20 + 5

E, para casos complexos, há uma ótima ferramenta bc :

echo "20+5" | bc

Entre, bc pode calcular até mesmo expressões muito complexas com raízes, logaritmos, cos, sin e assim por diante.

    
por 14.06.2012 / 16:47
23

As soluções mencionadas são boas para cálculos muito simples, mas muito propensas a erros. Exemplos:

# without spaces expr 20+5 produces literally 20+5
expr 20+5
→ 20+5

# bc's result doesn't give the fractional part by default
bc <<< 9.0/2.0
→ 4

# expr does only integer
expr 9 / 2
→ 4

# same for POSIX arithmetic expansion
echo $((9/2))
→ 4

# bash arithmetic expansion chokes on floats
echo $((9.0/2.0))
→ bash: 9/2.0: syntax error: invalid arithmetic operator (error token is ".0")

# Most 'expr' implementations also have problems with floats
expr 9.0 / 2.0
→ expr: non-integer argument

Um erro de sintaxe como os últimos é facilmente percebido, mas respostas inteiras com uma parte flutuante descartada podem facilmente passar despercebidas e levar a resultados errados.

É por isso que eu sempre uso uma linguagem de script como Lua para isso. Mas você pode escolher qualquer linguagem de script com a qual esteja familiarizado. Eu apenas uso Lua como um exemplo. As vantagens são

  • uma sintaxe familiar
  • funções familiares
  • ressalvas familiares
  • entrada flexível
  • espaços geralmente não importam
  • saída de ponto flutuante

Exemplos:

lua -e "print(9/2)"
→ 4.5

lua -e "print(9 / 2)"
→ 4.5

lua -e "print(9.0/2)"
→ 4.5

lua -e "print (9 /2.)"
→ 4.5

lua -e "print(math.sqrt(9))"
→ 3
    
por 14.06.2012 / 17:55
21

Ninguém mencionou o awk ainda?

Usando as funções do shell POSIX e o poder matemático do awk, apenas defina esta função (uma linha):

calc(){ awk "BEGIN { print $*}"; }

Em seguida, basta executar coisas como calc 1+1 ou calc 5/2

Nota: Para tornar a função sempre disponível, adicione-a a ~ / .bashrc (ou ao arquivo de inicialização do seu shell correspondente)

Claro, um pequeno script chamado "calc" com o seguinte conteúdo:

#!/bin/sh -
awk "BEGIN { print $* }"

também poderia funcionar.

    
por 15.06.2012 / 20:30
17

Você pode usar bc . Por exemplo,

$ echo "25 + 5" | bc
30

Como alternativa, bc <<< 25+5 também funcionará.

Ou interativamente, se você quiser fazer mais do que apenas um simples cálculo:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'. 
25 + 5
30

A implementação GNU de bc imprime as informações de cabeçalho / direitos autorais na inicialização quando ambos, stdin e stdout, vão para um terminal. Você pode suprimi-lo com a opção -q (específica do GNU). Para mais informações, consulte a página man do bc

    
por 14.06.2012 / 16:46
16

Você pode usar calc :

Se você digitar calc sem nenhum outro argumento, ele entrará em um modo interativo onde você poderá continuar fazendo a matemática. Você sai disso digitando exit:

C-style arbitrary precision calculator (version 2.12.3.3)
Calc is open software. For license details type:  help copyright
[Type "exit" to exit, or "help" for help.]

; 2+4
6
; 3+5
8
; 3.4+5
8.4
; 2^4
16
; exit

Ou você o usa com a expressão como um argumento e fornecerá a resposta e, em seguida, sairá

$calc 2 + 4
    6
$

calc é semelhante a bc , gosto da maneira como se comporta como padrão melhor

    
por 14.06.2012 / 19:20
10

Eu gosto de ativar o Python e usá-lo como uma calculadora interativa (mas, novamente, sou um programador Python).

    
por 14.06.2012 / 23:03
10

Como ninguém mais mencionou isso, e embora não seja estritamente uma calculadora (mas nem todas essas linguagens de script de propósito geral), gostaria de mencionar units :

$ units "1 + 1"
        Definition: 2
$ units "1 lb" "kg"
        * 0.45359237
         / 2.2046226

Ou, para menos resultados, você pode obter apenas o número a ser usado em $() para atribuir algo:

$ units -t "1 + 1"
2
$ units -t "1 lb" "kg"
0.4539237

E até faz conversões de temperatura

$ units -t "tempC(20)" "tempF"
68

Para obter a conversão de temperatura em uma expressão para cálculo adicional, faça o seguinte:

$ units -t "~tempF(tempC(20))+1"
68.1
    
por 15.06.2012 / 19:40
6
$> ghc -e '20 + 5'
25
it :: Integer

Também ghci , ou seja, o Compilador Glasgow-Haskell em vídeos interativos mode ( ghc --interactive , ao contrário de avaliar uma expressão com -e ), cria uma "calculadora" fascinante:

$>ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> pi
3.141592653589793
Prelude> ceiling pi
4
Prelude> compare 1 2
LT
    
por 15.06.2012 / 09:05
4

Eu uso um pequeno script python que irá avaliar uma expressão python e imprimir o resultado, então eu posso executar algo como

$ pc '[i ** 2 for i in range(10)]'
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

o script é:

#!/usr/local/bin/python3

import sys
import traceback
from codeop import CommandCompiler

compile = CommandCompiler()
filename = "<input>"
source = ' '.join(sys.argv[1:]) + '\n'

try:
    code = compile(source, filename) 
except (OverflowError, SyntaxError, ValueError):
    type, value, sys.last_traceback = sys.exc_info()
    sys.last_type = type
    sys.last_value = value
    if filename and type is SyntaxError:
        # Work hard to stuff the correct filename in the exception
        try:
            msg, (dummy_filename, lineno, offset, line) = value.args
        except ValueError:
            # Not the format we expect; leave it alone
            pass
        else:
            # Stuff in the right filename
            value = SyntaxError(msg, (filename, lineno, offset, line))
            sys.last_value = value
    lines = traceback.format_exception_only(type, value)
    print(''.join(lines))
else:
    if code:
        exec(code)
    else:
        print('incomplete')

Infelizmente, não me lembro de onde peguei a maior parte do código, por isso não posso citá-lo.

    
por 18.06.2012 / 03:46
4

Gnuplot

gnuplot - um programa de plotagem interativo
Siga o link acima ou digite gnuplot do prompt então help dentro do interpretador do gnuplot . O Gnuplot é um programa criado para traçar dados, mas pode ser usado para cálculo também. Ele oferece a vantagem de poder definir funções e usar as internas.

echo  "pr 20+5/2"  |  gnuplot          #  Lazy-note 'pr' instead of print
22                                     #  Integer calculation & result
echo  "pr 20.+5/2"  |  gnuplot         #  Lazy-note 'pr' instead of print
22.0                                   #  Floating point result
echo  "pr sin(2*pi/3.)"  |  gnuplot    #  Some functions ...
0.866025403784439

Root (ou algum outro interpretador C )

The ROOT system provides a set of OO frameworks with all the functionality needed to handle and analyze large amounts of data in a very efficient way...

Você pode usá-lo como interpretador C , CINT , ou você pode usar um dos muitos outros interpretadores de C . IMHO, é enorme, complexo, poderoso e nem sempre amigável, mas pode dar grande satisfação também.

Se você realmente não quer ouvir a pequena voz dentro de você que cita Confúcio e você está pronto para quebrar uma mosca (manteiga) na roda você pode usar root . Nesse caso, -l é obrigatório para evitar mostrar a tela inicial ...

echo  "20+5/2"   | root -l
(const int)22
echo  "20+5/2."  | root -l
(const double)2.25000000000000000e+01

echo  "cout<< 20+5/2 << endl;"   | root -l
22
    
por 11.06.2014 / 00:58
4

Para aritmética Integer (onde 3/2 = 1)

  • bash echo $(( 1+1 ))
  • fish math 1+1
  • zsh* echo $((1+1))

*: e ksh93, yash

Para aritmética de ponto flutuante (onde 3/2 = 1,5)

  • bash awk "BEGIN {print 10/3}" (baixa precisão)
  • bash echo "10/3"|bc -l (alta precisão)
  • fish math -s4 10/3
  • zsh* echo $((10./3))

*: e ksh93, yash

Você pode configurar seu shell para usar o awk com um mínimo de digitação como calc 10/3 (veja notas sobre como fazer isso para bash 1 e fish 2 ).

O principal motivo para sugerir o awk for bash é que ele está pré-instalado em quase todos os sistemas operacionais Unix e é razoavelmente leve (há, é claro, o custo de iniciar um processo) com uma saída menos precisa, mas mais amigável do que bc -l que imprime 20 dígitos decimais (embora você possa certamente ajustar o awk para obter mais dígitos decimais ).

Notas

(1) Como usar a sintaxe simplificada no bash

Adicione esta função bash ao seu ~/.bashrc :

calc(){ awk "BEGIN { print $*}"; }

(2) Como usar a sintaxe simplificada em peixes

Crie uma função calc fish (ou seja, um arquivo de texto chamado /home/ndemou/.config/fish/functions/calc.fish ):

function calc
    awk "BEGIN{ print $argv }" ;
end
    
por 20.04.2015 / 18:07
3

Para cálculos de console, eu uso concalc . ( sudo aptitude install concalc )

Depois disso, basta digitar concalc e apertar enter. Não irá fornecer um prompt, mas apenas digite o seu cálculo (sem espaços) e aperte enter, e na próxima linha, ele dará o valor numérico.

    
por 14.06.2012 / 22:33
3

Eu não posso acreditar em ler "o poder do JavaScript" (mas eu tive que votar positivamente na resposta para as outras partes, exceto perl, é claro).

Praticamente, para os casos simples em que aritmética inteira é suficiente, eu uso o buildin $ ((...)) e o recomendo. Senão, em quase todos os casos, echo "..." | bc é suficiente.

Para algumas operações aritméticas, como estatísticas, operações de matriz e mais R , é a melhor ferramenta:

echo 25 + 5 | R --vanilla

e para pequenos conjuntos de dados e resultados gráficos descartáveis, oocalc é um bom utilitário.

    
por 14.06.2012 / 23:52
3

SQLite :

echo 'select 1 + 1;' | sqlite3 

MySQL :

mysql -e 'select 1 + 1 from dual;'

PostgreSQL :

psql -c 'select 1 + 1 as sum;'
    
por 16.06.2012 / 16:38
2

Use a biblioteca aritmética de precisão múltipla GNU através do programa run-expr fornecido:

  • Faça o download e extraia (você precisará do lzip): tar -xvf gmp-5.1.3.tar.lz
  • No diretório superior, ./configure e make (não é necessário instalar)
  • Em demonstrações / expr, make run-expr
  • Eu gosto de criar um link simbólico para ele no meu diretório ~/bin : ln -s /path/to/gmp/demos/expr/run-expr ~/bin/run-expr
  • Adicione um alias para facilitar o uso; por exemplo alias calcf='run-expr -f' para avaliação de ponto flutuante

Saída:

# calcf '2/3'
"2/3" base 0: result 0.666666666666666666667e0

Do arquivo run-expr.c :

Usage: ./run-expr [-z] [-q] [-f] [-p prec] [-b base] expression...

   Evaluate each argument as a simple expression.  By default this is in mpz
   integers, but -q selects mpq or -f selects mpf.  For mpf the float
   precision can be set with -p.  In all cases the input base can be set
   with -b, or the default is "0" meaning decimal with "0x" allowed.

Consulte o manual para ver as diferenças e detalhes das classes de função.

    
por 26.02.2014 / 12:27