Journal Calculs numériques en précision absolue.

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
13
28
sept.
2017

Sommaire

Introduction

La lecture de ce journal m'a remémoré une bibliothèque de calcul numérique que j'ai développée et qui pourrait peut-être en intéresser quelques-uns ici.

J'ai rarement utilisé les nombres flottants à cause de leur précision limitée, et les entiers se sont parfois révélés inadaptés de par leur intervalles limités. Aussi ai-je développé une bibliothèque de gestion d'entiers dynamiques, et, en m'appuyant sur cette dernière, une bibliothèque de gestion de nombres rationnels qui prend en charge les 4 opérations mathématiques de base avec une précision absolue.

Les logiciels que je présente ici ne sont, pour l'instant, que capable de calculer le résultat d'une chaîne de caractères contenant une expression numérique. Ce calcul peut se réaliser à l'aide d'un utilitaire en ligne de commande, d'un addon Node.js, ou d'un composant Java.

Il est possible d'essayer cette bibliothèque en ligne, pour peu que l'on ai quelques rudiments en Javascript et le navigateur adéquat, en se rendant à cette adresse : http://npm.runkit.com/rncq/.

L'expression à évaluer peut être algébrique (1 + 2 / 3) ou RPN (1 2 + 3 /). La version en ligne de commande propose en outre deux options :

  • --to-float qui convertit le résultat final en float,
  • --use-float qui réalise le calcul à l'aide du type float.

La mise en œuvre d'une de ces deux options peut avoir des résultats inattendus, de par la précision limité du type float, mais aussi parce que les calculs peuvent aboutir à des nombres qui dépassent largement les capacités du type float.

Les expressions

Formats

Une expression peut être exprimée au format algébrique (1 + 2 * 3) ou RPN (1 2 3 * +). Elle peut contenir un nombre décimal (le séparateur est . ou ,), auquel cas il est convertit en sa fraction équivalente. Par exemple, 12.345 est convertit en 2469/200 (qui est égal à 12345/1000).

Les opérateurs reconnus sont :

  • + pour l'addition,
  • - pour la soustraction,
  • *, xet X pour la multiplication,
  • / et : pour la division.

Lorsque l'expression à évaluer est un argument de ligne de commande, il faut prendre garde aux opérateurs utilisés. Par exemple, l'opérateur de multiplication usuel (*) peut poser problème sous système POSIX, car l'interpréteur le remplace par une liste de fichiers ; il faut donc l'échapper (\*), mettre l'expression entre guillemets ou utiliser l'un des symboles alternatifs (xou X). De la même manière, si l'expression contient des espaces, il faut mettre toute l'expression entre guillemets, pour qu'elle soit comprise par le programme comme un seul est unique argument.

Notation algébrique

C'est la notation usuelle, à savoir, par exemple, 1 + 2 * 3.

Les parenthèses ne sont actuellement pas reconnues, et la priorité des opérateurs n'est pas prise en compte (1+2*3 donne 9, et non pas 7).

les - et +unaires sont, eux, reconnus.

Notation RPN

C'est la notation dans laquelle on donne d'abord les arguments d'une opération avant de préciser l'opérateur qui doit être appliqué. Ainsi, l'équivalent de l'expression algébrique (1 + 2) * 3 sera 1 2 + 3 *(on voit que le format RPN permet de se passer de parenthèses).

Le - unaire n'est actuellement pas implémenté, aussi, pour entrer un nombre négatif, il convient d'écrire 0 <nombre> -.

Installation et utilisation

Généralités

Mis à part sous Windows, il faut qu'un environnement de compilation C++ soit installé.

Les différents paquets sont compilés :

  • sous environnement POSIX (y compris macOS et Cygwin), en lançant la commande make à la racine du package,
  • sous Windows,
    • en lançant la compilation du .vcxproj dans Visual Studio,
    • sous Cygwin, voir ci-dessus (environnement POSIX) , sachant que :
      • par défaut, le binaire produit utilisera l'API Cygwin,
      • en passant l'argument target=win (voire target=win32 ou target=win64 pour produire explicitement une version IA-32 ou AMD64 du binaire), si la version adéquate de mingw est installée, on obtient un binaire utilisant l'API Windows.

À noter que les binaires Windows d'un paquet sont directement disponibles dans la section releases du repository GitHub dudit paquet.

Si le paquet est directement lié à un framework tiers, il est possible que le framewok en question impose la manière dont le paquet doit être compilé. Il faudra alors voir la documentation dudit framework.

Node.js

GitHub : http://github.com/epeios-q37/rncq-node

NPM

Le composant étant disponible sur NPM, il suffit de lancer npm install rncq. Excepté sous Windows, il faut qu'un environnement de compilation C++ soit installé.

Une fois installé, on peut lancer un test avec npm explore rncq -- node test.js, avec éventuellement, comme argument, une expression à évaluer. Par défaut, cette expression doit être en notation algébrique, mais en modifiant le fichier node_modules/rncq/test.js, on peut basculer en notation RPN (voir les commentaires dans le fichier en question).

Pour rappel, la version Node.js peut être testée en ligne sur Runkit (http://npm.runkit.com/rncq/).

JRE (Java).

GitHub : http://github.com/epeios-q37/rncq-java

il faut au préalable récupérer le wrapper Java, et lancer la compilation comme indiqué ci-dessus. Il faut que le Java Development Kit soit installé. Une fois le binaire compilé, il faudra le placer, ainsi que les fichiers jreq.xcfget jreq.xlcl, à la racine du paquet rncq-java (les fichiers .java et .class ne sont pas nécessaires).

Une fois le paquet rncq-java compilé (et les fichiers du wrapper mis en place), on peut lancer un test avec java RNCqTest, et éventuellement passer une expression numérique comme argument. On peut basculer en mode RPN en modifiant le fichier (qu'il faudra alors recompiler) RNCq.java (voir les commentaires dans ce fichier).

Ligne de commande

GitHub : http://github.com/epeios-q37/rncq-cli

Après compilation (voir ci-dessus), il suffit de lancer rncq avec l'expression numérique à évaluer.

Par défaut, l'expression doit être au format algébrique, mais avec l'option --rpn, on peut saisir une expression au format RPN. rncq --help permet d'afficher la liste des option disponibles.

Évolution

Je projette, pour les prochaines versions, d'exposer, afin de pouvoir y accéder directement, les différentes fonctions permettant de réaliser les calculs. Ceci dit, pour Node.js, je ne vois pas encore trop à quoi devrait ressembler l'API pour qu'elle soit non bloquante (s'il y en a qui ont des idées à ce propos…).

Il est également possible que je développe une version pour PHP, voire d'autres environnements d'exécution.

Je voudrais également améliorer le procédure d'installation, notamment pour la version Java, mais il n'existe (ou je n'ai pas trouvé) l'équivalent de NPM pour Java, donc je ne sais, pour l'instant, pas encore comment faire.

  • # Typo ?

    Posté par  (site web personnel) . Évalué à 5. Dernière modification le 28 septembre 2017 à 17:55.

    Je ne suis pas allé au bout, mais j'ai tiqué quand j'ai lu ça:
    (1 + 2 / 3) ou RPN (1 2 + 3 /)

    en RPN, 1 2 + 3 / ça fait 3/3 = 1

    Tandis que d'après les règles de priorité des opérateurs, 1 + 2 / 3, c'est 1 + (2 / 3), soit 1,666666…
    Un oubli de parenthèses ?

    Edit:

    Les parenthèses ne sont actuellement pas reconnues, et la priorité des opérateurs n'est pas prise en compte

    C'est un peu gênant pour un outil destiné à faire du calcul ? Bon, après si c'est en développement… Je te conseille tout de même de ne pas mettre le mode algébrique en avant, ou le désactiver tant que la gestion standard n'est pas gérée, ça peut être source de confusion.

    • [^] # Re: Typo ?

      Posté par  (site web personnel, Mastodon) . Évalué à 2. Dernière modification le 28 septembre 2017 à 18:55.

      En fait il n'y a pas de parenthèses ou de priorité à reconnaitre, puisque tout l'intérêt de la RPN est justement qu'il n'y a plus besoin de gérer de parenthèses ou de priorité : tous les calculs sont faits instantanément.

      Mais c'est à l'utilisateur de rentrer le calcul dans le bon ordre : pour faire le calcul 1 + 2 / 3 en respectant la priorité du calcul écrit ainsi, il faut taper en RPN : 2 3 / 1 +. Mais une erreur sur ce point n'est plus une erreur de l'interpréteur, c'est une erreur d'ICC :)

      La connaissance libre : https://zestedesavoir.com

    • [^] # Re: Typo ?

      Posté par  . Évalué à 3.

      Je cite le journal :

      Les parenthèses ne sont actuellement pas reconnues, et la priorité des opérateurs n'est pas prise en compte (1+2*3 donne 9, et non pas 7).

      Tu n'es effectivement pas allé jusqu'au bout.

      Les vrais naviguent en -42

  • # Java

    Posté par  . Évalué à 1.

    J'ai peut-être lu un peu vite, mais en java le format de distribution binaire est le jar.
    Il existe des dépôts comme ceux de Maven, mais je ne sais pas comment on ajoute des paquets dedans.

  • # Existant ?

    Posté par  (site web personnel) . Évalué à 3.

    Dans le même genre, il y a libgmp :

    https://gmplib.org/

    • [^] # Re: Existant ?

      Posté par  (site web personnel) . Évalué à 5.

      Sachant que libgmp est massivement utilisée, c'est au moins le support des "bigint" et "rational" en python et Haskell, sans doute aussi dans d'autres langages.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.