web-dev-qa-db-fra.com

Comment faire des calculs d'entiers et de flottants, en bash ou dans d'autres langages / frameworks?

L'utilisation de echo "20+5" Produit littéralement le texte "20+5".

Quelle commande puis-je utiliser pour obtenir la somme numérique, 25 Dans ce cas?

De plus, quelle est la façon la plus simple de le faire en utilisant bash pour virgule flottante? Par exemple, echo $((3224/3807.0)) imprime 0 :(.

Je recherche des réponses en utilisant soit la commande de base Shell ("ligne de commande") elle-même, soit en utilisant des langues disponibles à partir de la ligne de commande.

316
Michael Durrant

Il y a beaucoup d'options !!!

Sommaire

$ 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

Détails

Coquilles

Vous pouvez utiliser l'expansion arithmétique POSIX pour entier arithmétique echo "$((...))":

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

Assez portable (ash dash yash bash ksh93 lksh zsh):
.

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

ksh93, yash et zsh supporte les flottants ici:

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

uniquement ksh93 (directement) et zsh chargement de la bibliothèque mathfunc ici:

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

(zsh doit charger zmodload zsh/mathfunc pour obtenir des fonctions comme atan).


De manière interactive avec zsh:

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

Avec (t) csh (entier uniquement):

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

Dans la famille rc Shell, akanga est celle avec une expansion arithmétique:

; echo $:25/3
8

POSIX toolchest

bc (voir ci-dessous pour le mode interactif), manuel ici

Mnémonique: best calculator (bien que le b soit en fait pour basique).

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

(prend en charge les nombres de précision arbitraires)


mode interactif 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

Rush solution, expr (pas de mode interactif):

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

solution de Joshua : awk (pas de mode interactif):

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

Autres outils plus ou moins portables

Arcege solution, dc (mode interactif: dc):

Ce qui est encore plus amusant car il fonctionne en notation polonaise inversée.

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

Mais ce n'est pas aussi pratique, sauf si vous travaillez souvent avec la notation polonaise inversée.

Notez que dc est antérieur à bc et bc a été historiquement implémenté comme un wrapper autour de dc mais dc n'a pas été standardisé par POSIX


DQdimscalc (obligatoire Sudo apt-get install apcalc):

$ calc 2 + 4
6

Interprètes de langue à usage général:

manatwork 's solution, node (mode interactif: node; fonction de sortie non nécessaire):

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

Perl (mode interactif: Perl -de 1):

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

Python (mode interactif: python; fonction de sortie non nécessaire):

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

Prend également en charge les nombres de précision arbitraires:

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

Si vous avez clisp installé, vous pouvez également utiliser la notation polonaise:

$ clisp -x "(+ 2 2)"

Marco solution, lua (mode interactif: lua):

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

[~ # ~] php [~ # ~] (mode interactif: php -a):

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

Ruby (mode interactif: irb; fonction de sortie non nécessaire):

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

Guile (mode interactif: guile):

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

S-Lang (mode interactif: slsh; fonction de sortie non nécessaire, juste un terminateur ;):

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

Tcl (mode interactif: tclsh; fonction de sortie non nécessaire, mais expr l'est):

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

Coquilles 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
>

Divers SQL:

SQLite (mode interactif: 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

_Les options sur mysql et postgres arrêtent l'image 'ascii art'!

Langues spécialisées orientées mathématiques:

[~ # ~] r [~ # ~] en mode simple - permet de générer 1000 nombres aléatoires normaux et d'obtenir l'écart-type et de l'imprimer

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

[~ # ~] r [~ # ~] en utilisant le littler script - permet d'imprimer pi au carré

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

PARI/GP , un système d'algèbre informatique étendu pour la théorie des nombres, l'algèbre linéaire et bien d'autres choses

$ 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

Octave GNU (un langage interprété de haut niveau, principalement destiné aux calculs numériques)

Prend également en charge les nombres complexes:

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

Julia , langage performant et interprète pour l'informatique scientifique et numérique.

Option non interactive:

$ Julia -E '2.5+3.7'
6.2
431
lgarzo

Il existe de nombreuses façons de calculer. Pour les expressions simples, vous pouvez utiliser bash lui-même:

echo $((20+5))

ou expr:

expr 20 + 5

Et pour les cas complexes, il existe un excellent outil bc:

echo "20+5" | bc

Btw, bc peut calculer une expression même très complexe avec des racines, des logarithmes, cos, sin et ainsi de suite.

37
rush

Les solutions mentionnées conviennent parfaitement pour des calculs très simples, mais sont très sujettes aux erreurs. Exemples:

# 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

Une erreur de syntaxe comme les dernières se remarque facilement, mais les réponses entières avec une partie flottante rejetée peuvent facilement passer inaperçues et conduire à des résultats erronés.

C'est pourquoi j'utilise toujours un langage de script comme Lua pour cela. Mais vous pouvez choisir n'importe quel langage de script que vous connaissez. J'utilise juste Lua comme exemple. Les avantages sont

  • une syntaxe familière
  • fonctions familières
  • mises en garde familières
  • entrée flexible
  • les espaces n'ont généralement pas d'importance
  • sortie en virgule flottante

Exemples:

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

Personne n'a encore mentionné awk?

En utilisant les fonctions POSIX Shell et la puissance mathématique awk, il suffit de définir cette fonction (une ligne):

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

Ensuite, exécutez simplement des choses comme calc 1+1 ou calc 5/2

Remarque: pour que la fonction soit toujours disponible, ajoutez-la à ~/.bashrc (ou au fichier de démarrage de votre shell correspondant)

Bien sûr, un petit script nommé "calc" avec le contenu suivant:

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

pourrait également fonctionner.

25
Joshua

Vous pouvez utiliser bc. Par exemple.,

$ echo "25 + 5" | bc
30

Alternativement bc <<< 25+5 fonctionnera également.

Ou de manière interactive, si vous voulez faire plus qu'un simple calcul simple:

$ 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

L'implémentation GNU de bc imprime ces informations d'en-tête/copyright au démarrage lorsque ses stdin et stdout vont à un terminal. Vous pouvez les supprimer avec le (spécifique à GNU ) -q option. Pour plus d'informations, consultez la page de manuel bc

18
Levon

Vous pouvez utiliser calc:

Si vous entrez simplement calc sans aucun autre argument, il entre dans un mode interactif où vous pouvez continuer à faire des calculs. Vous quittez cela en tapant 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 vous l'utilisez avec l'expression comme argument et il fournira la réponse, puis quitter

$calc 2 + 4
    6
$

calc est similaire à bc, j'aime juste la façon dont il se comporte mieux par défaut

17
DQdlM

J'aime lancer Python et l'utiliser comme une calculatrice interactive (mais là encore, je suis un programmeur Python)).

10
asmeurer

Puisque personne d'autre ne l'a mentionné, et bien que ce ne soit pas strictement une calculatrice (mais pas tous ces langages de script à usage général), je voudrais mentionner units:

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

Ou, pour moins de sortie, vous pouvez obtenir juste le nombre à utiliser dans $() pour attribuer à quelque chose:

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

Et il fait même des conversions de température

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

Pour obtenir la conversion de température dans une expression pour un calcul supplémentaire, procédez comme suit:

$ units -t "~tempF(tempC(20))+1"
68.1
10
Random832

Pour l'arithmétique entière (où 3/2 = 1)

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

*: et ksh93, yash

Pour l'arithmétique à virgule flottante (où 3/2 = 1,5)

  • bashawk "BEGIN {print 10/3}" (faible précision)
  • bashecho "10/3"|bc -l (haute précision)
  • fishmath -s4 10/3
  • zsh*echo $((10./3))

*: et ksh93, yash

Vous pouvez bien sûr configurer votre Shell pour utiliser awk avec un minimum de frappe comme calc 10/3 (Voir les notes sur la façon de le faire pour bash1 et du poisson2).

La principale raison de suggérer awk pour bash est qu'il est préinstallé sur presque tous les systèmes d'exploitation de type Unix et qu'il est raisonnablement léger (il y a bien sûr le coût de démarrage d'un processus) avec une sortie moins précise mais plus conviviale que bc -l qui affiche 20 chiffres décimaux (bien que vous puissiez certainement Tweak awk pour obtenir plus de chiffres décimaux ).


Remarques

(1) Comment utiliser la syntaxe simplifiée dans bash

Ajoutez cette fonction bash à votre ~/.bashrc:

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

(2) Comment utiliser la syntaxe simplifiée chez les poissons

Créez une fonction poisson calc (c'est-à-dire un fichier texte nommé /home/ndemou/.config/fish/functions/calc.fish):

function calc
    awk "BEGIN{ print $argv }" ;
end
6
ndemou
$> ghc -e '20 + 5'
25
it :: Integer

ghci, c'est-à-dire le Glasgow-Haskell Compiler en mode interactif (ghc --interactive, par opposition à l'évaluation d'une expression avec -e ), fait une "calculatrice" 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

J'utilise un petit script python qui évaluera une expression python et afficherai le résultat, puis je pourrai exécuter quelque chose comme

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

le script est:

#!/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')

Malheureusement, je ne me souviens pas d'où j'ai emprunté la plupart du code, donc je ne peux pas le citer.

4
cobbal

Gnuplot

gnuplot - un programme de traçage interactif
Suivez le lien ci-dessus ou tapez gnuplot à partir de l'invite puis help à l'intérieur de gnuplot interpréteur.
Gnuplot est un programme né pour tracer des données, mais peut également être utilisé pour le calcul. Il offre l'avantage que vous pouvez définir des fonctions et/ou utiliser celles intégrées.

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

Racine (ou un autre interpréteur C )

Le système ROOT fournit un ensemble de cadres OO avec toutes les fonctionnalités nécessaires pour gérer et analyser de grandes quantités de données dans un très moyen efficace ...

Vous pouvez l'utiliser comme interpréteur C , [~ # ~] cint [~ # ~] , ou vous pouvez utiliser l'un des beaucoup d'autres interpréteurs C . À mon humble avis, c'est énorme, complexe, puissant et pas toujours sympathique, mais peut aussi donner une grande satisfaction.

Si vous ne voulez vraiment pas écouter la petite voix en vous qui cite Confucio et vous êtes prêt à casser une (beurre) mouche sur la roue vous pouvez utiliser root . Dans ce cas -l est obligatoire pour éviter d'afficher l'écran de démarrage ...

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

Je ne peux pas croire lire "la puissance de JavaScript" (mais j'ai dû voter pour la réponse pour les autres parties, sauf Perl bien sûr.

Pratiquement, pour les cas simples où l'arithmétique entière est suffisante, j'utilise le buildin $ ((...)) et le recommande. Sinon, dans presque tous les cas, l'écho "..." | bc est suffisant.

Pour certaines opérations arithmétiques comme les statistiques, les opérations matricielles, etc. R est le meilleur outil:

echo 25 + 5 | R --Vanilla

et pour les petits ensembles de données et les résultats graphiques à jeter, oocalc est un utilitaire sympa.

4
user unknown

Pour les calculs sur console, j'utilise concalc. (Sudo aptitude install concalc)

Après cela, tapez simplement concalc et appuyez sur Entrée. Il ne fournira pas d'invite, mais tapez simplement votre calcul (pas d'espaces) et appuyez sur Entrée, et sur la ligne suivante, il vous donnera la valeur numérique.

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

Utilisez la GNU Multiple Precision Arithmetic Library via le run-expr programme:

  • Téléchargez et extrayez (vous aurez besoin de lzip): tar -xvf gmp-5.1.3.tar.lz
  • Dans le répertoire supérieur, ./configure et make (pas besoin d'installer)
  • Dans les démos/expr, make run-expr
  • J'aime créer un lien symbolique vers celui-ci dans mon ~/bin répertoire: ln -s /path/to/gmp/demos/expr/run-expr ~/bin/run-expr
  • Ajoutez un alias pour une utilisation facile; par exemple alias calcf='run-expr -f' pour l'évaluation en virgule flottante

Production:

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

Du run-expr.c fichier:

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.

Voir le manuel pour les différences et les détails des classes de fonctions.

2
user44370

Les autres solutions ici présentent toutes des inconvénients notables.

J'ai donc créé une nouvelle commande pour pouvoir le faire de la manière la plus simple et la plus fiable.

Échantillons:

$ 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