IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Calcul scientifique Python Discussion :

Problématique de stockage de très grands nombres


Sujet :

Calcul scientifique Python

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Casse-Cou
    Inscrit en
    Février 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Casse-Cou

    Informations forums :
    Inscription : Février 2016
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Problématique de stockage de très grands nombres
    Bonjour,
    Dans le cadre d'un projet perso, je m'amuse à manipuler de très grands nombres (jusqu'à 300 chiffres) en python.
    Magiquement, aucun soucis niveau python, qui les gère nativement.

    Le problème se pose au stockage.
    Je cherche un moyen efficace (aussi bien en termes de temps de traitement que de place) de stocker mes très grands nombres.

    Solutions envisagées :

    • fichier texte classique : le hic ici est le poid du fichier. Traiter des très grands nombres comme des chaines de caractère est une perte de place évidente ...
    • fichier binaire : Avec le module struct, cela me permettrai en théorie (il me semble) d' avoir le "meilleur rendement" en terme d'espace. cependant problème : Il semblerai que ce module se base sur des formats types C; Et est donc limité en terme de taille d'int, long voir longlong.



    D'où ma question, connaissez vous un moyen efficace de stocker des int dynamique tel que ceux utilisés par Python ?

    À noter : Les nombres que je cherche à stocker n'ont pas de taille fixe.

    Piste en travaux actuellement :
    ->Créer mon propre format binaire de stockage d'int :
    Si je code un chiffre sur 4 bits, cela me donne 16 valeurs possibles il me reste donc 4 valeurs pour coder des séparateurs et autres ...
    donc 1 octet = 2 chiffres.
    Sachant que mes nombres employés ont entre 1 et 300 chiffres => je m'en sort à 1o-150o
    c'est mieux que de considérer mes entiers comme des chars, mais ça reste plus que d'écrire directement le nombre en binaire :
    10^300 correspondant grosso modo à 128o sachant qu'il manque le séparateur dans ce cas.

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Qu'appelle-tu une taille de fichier insupportable ?

    Un nombre de 300 chiffres dans un fichier binaire aura une taille de 300 octets. Il sera écrit ou lu en un temps insignifiant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    >>> x
    197517781769395718205196310223432292069410886056244510796349431604888502695520674819086640166067014052824635018648300214692406548595644254129017903358423455193367673208551802127114520663707196114373772729273738978670150542758209575144988338424105178091558439135035201630552844261045411268747079276545370367756743150610602221633232198758714558189976
    >>> len(str(x))
    348
    >>> with open('bignumber', 'wb') as outf:
    ...     outf.write(str(x).encode('ascii'))
    ... 
    348
    >>> os.path.getsize('bignumber')
    348
    >>> with open('bignumber', 'rb') as inf:
    ...     x = int(inf.read())
    ... 
    >>> x
    197517781769395718205196310223432292069410886056244510796349431604888502695520674819086640166067014052824635018648300214692406548595644254129017903358423455193367673208551802127114520663707196114373772729273738978670150542758209575144988338424105178091558439135035201630552844261045411268747079276545370367756743150610602221633232198758714558189976

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Casse-Cou
    Inscrit en
    Février 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Casse-Cou

    Informations forums :
    Inscription : Février 2016
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Qu'appelle-tu une taille de fichier insupportable ?
    Actuellement, 1Milliard d'entrées...

    Citation Envoyé par VinsS Voir le message
    Un nombre de 300 chiffres dans un fichier binaire aura une taille de 300 octets. Il sera écrit ou lu en un temps insignifiant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    [...]
    >>> with open('bignumber', 'wb') as outf:
    ...     outf.write(str(x).encode('ascii'))
    [...]
    Je cherche un moyen de l'enregistrer sans considérer mon nombre comme une suite de caractère pour éviter ce ratio de 1chiffre pour 1o, qui n'est pas nécessaire vu que je n'écris que des entiers.

    D'ailleurs, y a t'il une différence entre ton write ci-dessus et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    with open('bignumber','w') as outf:
            outf.write(str(x))

  4. #4
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Salut,

    Tu peux pas juste utiliser pickle? Pickle travaille en binaire et son en-tete rajoute juste 8 bytes.

    Sinon, tu peux stocker en binaire, mais va falloir te creer un format maison pour separer tes int(longueur int, separateur, ...). Autant utiliser pickle.

    Sinon, Python3 offre to_bytes, qui est pratique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    >>> int(50000).to_bytes(2, "big")
    b'\xc3P'
    En python2, tu peux juste convertir en hex et stocker:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    >>> binascii.unhexlify("%x" % 50000)
    '\xc3P'

  5. #5
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Non, il n'y a pas de différence de taille de fichier, c'est par réflexe que j'ouvre le fichier en mode binaire.

    J'allais te dire que en hexadécimal le nombre se réduit significativement en taille mais dahtah te fournit une réponse plus utile.

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Casse-Cou
    Inscrit en
    Février 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Casse-Cou

    Informations forums :
    Inscription : Février 2016
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par dahtah Voir le message
    Tu peux pas juste utiliser pickle? Pickle travaille en binaire et son en-tete rajoute juste 8 bytes.
    Après test, pickle stocke les entiers comme des strings, et ne corrige pas le problème de poid de fichier.

    Citation Envoyé par dahtah Voir le message
    Sinon, tu peux stocker en binaire, mais va falloir te creer un format maison pour separer tes int(longueur int, separateur, ...). Autant utiliser pickle.
    C'est la piste que je creuse actuellement, j'ai en revanche peur pour les perfs(temps de calcul à l'écriture)
    Si cela intéresse des gens voici une ébauche du bousin (c'est très moche j'en conviens, ce n'est que pour le test pour l'instant) on obtient une écriture de 2chiffre pour 1 octet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    import binascii
     
    num2bin={}
    num2bin['0'] = '0000'
    num2bin['1'] = '0001'
    num2bin['2'] = '0010'
    num2bin['3'] = '0011'
    num2bin['4'] = '0100'
    num2bin['5'] = '0101'
    num2bin['6'] = '0110'
    num2bin['7'] = '0111'
    num2bin['8'] = '1000'
    num2bin['9'] = '1001'
    num2bin['NULL'] = '1111'
     
     
    a = '123456'
    paire = False
    chaineHex = ''
    tmp = ''
    for c in a:
    	if paire:
    		print str(c)+"->"+num2bin[c]
    		tmp += num2bin[c]
    		paire = False
    		hex = binascii.unhexlify('%x' % int('0b'+tmp, 2))
    		print tmp + '=>'+str(int('0b'+tmp,2)) +'=>' + hex
    		chaineHex = chaineHex+hex
    		tmp = ''
    	else:
    		print str(c)+"->"+num2bin[c]
    		tmp += num2bin[c]
    		paire = True
     
    if paire:
    	tmp += num2bin['NULL']
    	hex = binascii.unhexlify('%x' % int('0b'+tmp, 2))
    	chaineHex = chaineHex+hex
     
    print a +"================>"+chaineHex
    Citation Envoyé par dahtah Voir le message
    Sinon, Python3 offre to_bytes, qui est pratique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    >>> int(50000).to_bytes(2, "big")
    b'\xc3P'
    Ca m'a l'air prometteur, je testerai cela ce weekend.


    Citation Envoyé par dahtah Voir le message
    En python2, tu peux juste convertir en hex et stocker:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    >>> binascii.unhexlify("%x" % 50000)
    '\xc3P'
    Nickel ! je passe d'un string de 145 caractères à un string de 60. J'ai par contre l'impression d'avoir une limitation de taille au niveau de l'int en input. Je creuse

    En tout cas merci pour les infos .

Discussions similaires

  1. Problématique stockage de très grand graphe
    Par teddyalbina dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 27/12/2008, 15h31
  2. Précision d'un très très grand nombre
    Par sniperseb dans le forum Langage
    Réponses: 6
    Dernier message: 05/04/2006, 19h38
  3. Réponses: 2
    Dernier message: 22/12/2005, 18h16
  4. Trés grand nombre
    Par rteuteu55 dans le forum C++Builder
    Réponses: 10
    Dernier message: 15/11/2005, 11h28
  5. Une unité pour gérer des très grands nombres
    Par M.Dlb dans le forum Langage
    Réponses: 2
    Dernier message: 09/09/2003, 12h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo