ti-enxame.com

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

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

Que 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 o bash para ponto flutuante? Por exemplo, echo $((3224/3807.0)) imprime 0 :(.

Estou procurando respostas usando o próprio comando básico Shell ('linha de comando') ou usando os idiomas disponíveis na linha de comando.

316
Michael Durrant

Existem muitas opções !!!

Sumário

$ 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

Cartuchos

Você pode usar a expansão aritmética POSIX para 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 capacidade printf para imprimir carros alegóricos, podemos estender a maioria dos shells para fazer cálculos de ponto flutuante, embora com um intervalo limitado (não mais que 10 dígitos):

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

ksh93, yash e zsh suportam 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 número inteiro):

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

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

; echo $:25/3
8

Ferramentas POSIX

bc (veja abaixo o modo interativo), manual aqui

Mnemônico: bhusa calculator (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ários)


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 de Rush , expr (sem modo interativo):

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

solução de Josué : awk (sem modo interativo):

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

Outras ferramentas mais ou menos portáteis

Arcege 's solução, dc (modo interativo: dc):

O que é ainda mais divertido, pois funciona com notação polonesa reversa.

$ 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 reverso.

Observe que dc antecede bc e bc foram historicamente implementados como um wrapper em torno de dc mas dc não foi padronizado pelo POSIX


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

$ calc 2 + 4
6

Intérpretes de linguagem de uso geral:

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

$ 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ários:

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

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

$ clisp -x "(+ 2 2)"

Marco 's solução, 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 terminador ;):

$ 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

Shell Javascript :

$ 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 no postgres interrompem a imagem 'ascii art'!

Linguagens especializadas em matemática:

[~ # ~] 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 littler script - permite 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
431
lgarzo

Existem muitas maneiras de calcular. Para expressões simples, você pode usar bash:

echo $((20+5))

ou expr:

expr 20 + 5

E para casos complexos, existe uma ótima ferramenta bc:

echo "20+5" | bc

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

37
rush

As soluções mencionadas são adequadas 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 incorretos.

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

  • uma sintaxe familiar
  • funções familiares
  • advertências 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
25
Marco

Ninguém mencionou awk ainda?

Usando as funções POSIX Shell e awk math power, basta definir 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 em ~/.bashrc (ou no arquivo de inicialização do seu Shell correspondente)

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

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

também poderia funcionar.

25
Joshua

Você pode usar bc. Por exemplo.,

$ echo "25 + 5" | bc
30

Alternativamente bc <<< 25+5 também funcionará.

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

$ 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 essas informações de cabeçalho/direitos autorais na inicialização quando stdin e stdout vão para um terminal. Você pode suprimi-lo com o (GNU-specific ) -q opção. Para obter mais informações, consulte a página de manual do bc

18
Levon

Você pode usar calc:

Se você digitar calc sem outros argumentos, ele entrará em um modo interativo, onde você poderá continuar fazendo contas. Você sai dessa 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ê a usa com a expressão como argumento e ela fornecerá a resposta e sairá

$calc 2 + 4
    6
$

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

17
DQdlM

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

10
asmeurer

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

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

Ou, para menos saída, você pode obter apenas o número a ser usado em $() para atribuir a 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
10
Random832

Para aritmética de número inteiro (onde 3/2 = 1)

  • bashecho $(( 1+1 ))
  • fishmath 1+1
  • zsh*echo $((1+1))

*: e ksh93, yash

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

  • bashawk "BEGIN {print 10/3}" (baixa precisão)
  • bashecho "10/3"|bc -l (alta precisão)
  • fishmath -s4 10/3
  • zsh*echo $((10./3))

*: e ksh93, yash

Obviamente, você pode configurar seu Shell para usar o awk com digitação mínima como calc 10/3 (Consulte as notas sobre como fazer isso para o bash1 e peixe2).

A principal razão para sugerir o awk para o bash é que ele é pré-instalado em quase todos os sistemas operacionais semelhantes ao Unix e é razoavelmente leve (é claro que existe o custo de iniciar um processo) com uma saída menos precisa, mas mais amigável ao homem do que bc -l, que imprime 20 dígitos decimais (embora você possa certamente Tweak 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
6
ndemou
$> ghc -e '20 + 5'
25
it :: Integer

Também ghci, que é o Compilador de Glasgow-Haskell no modo interativo (ghc --interactive, em vez 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
6

Eu uso um pouco de script python que avalia uma expressão python e imprime 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 emprestado a maior parte do código, então não posso citá-lo.

4
cobbal

Gnuplot

gnuplot - um programa de plotagem interativo
Siga o link acima ou digite gnuplot no prompt e depois help dentro do gnuplot intérprete.
O Gnuplot é um programa criado para plotar dados, mas também pode ser usado para o cálculo. Oferece a vantagem de poder definir funções e/ou usar as incorporadas.

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

Raiz (ou algum outro intérprete C )

O sistema ROOT fornece um conjunto de estruturas OO) com toda a funcionalidade necessária para manipular e analisar grandes quantidades de dados de uma maneira muito maneira eficiente ...

Você pode usá-lo como intérprete C , [~ # ~] cint [~ # ~] , ou você pode usar um dos muitos outros intérpretes C . IMHO, é enorme, complexo, poderoso e nem sempre amigável, mas também pode dar uma grande satisfação.

Se você realmente não quer ouvir a vozinha dentro de você que cita Confucio e você está pronto para quebrar uma (manteiga) mosca no volante você pode usar raiz . 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
4
Hastur

Não posso acreditar em ler "o poder do JavaScript" (mas tive que aprovar a resposta para as outras partes, exceto Perl, é claro.

Na prática, nos casos simples em que a aritmética inteira é suficiente, eu uso o buildin $ ((...)) e o recomendo. Senão, em quase todos os casos ecoam "..." | 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 fora de uso, oocalc é um utilitário agradável.

4
user unknown

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

Depois disso, digite concalc e pressione enter. Ele não fornecerá um prompt, mas basta digitar seu cálculo (sem espaços) e pressionar enter e, na próxima linha, fornecerá o valor numérico.

3
killermist

SQLite:

echo 'select 1 + 1;' | sqlite3 

MySQL:

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

PostgreSQL:

psql -c 'select 1 + 1 as sum;'
3
Vidul

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)
  • Nas demos/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

Resultado:

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

No 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 obter diferenças e detalhes das classes de funções.

2
user44370

O restante das soluções aqui tem desvantagens notáveis.

Então, eu criei um novo comando para poder fazer isso da maneira mais simples e confiável.

Amostras:

$ solve 1/5
0.2
$ solve 1.5+3.1
4.6
$ solve 1/1000000
1e-06
$ solve 7+2^3
15
$ solve "sqrt(8)"
2.82842712474619
$ solve 1/0
non solvable ????: 1/0
0
Alberto Salvia Novella