J'ai une variable en python contenant un numéro de point flottant (par exemple, Je pensais d'abord à utiliser la représentation de chaîne (via EDIT: B> P> bons points ci-dessous. Je devrais clarifier. Le nombre est déjà un flotteur et est poussé à une base de données via cx_oracle. J'essaie de faire de la meilleure chose que je puisse en python pour gérer des flotteurs trop volumineux pour le type de base de données correspondant à l'exécution des erreurs d'insertion et de manipulation d'Oracle (car je veux faire face aux numéros de champ, pas d'enregistrement, pas à un temps). Je suppose que num = 24654.123 code>), et j'aimerais déterminer les valeurs de précision et d'échelle du nombre (dans le sens Oracle), donc 123.45678 devrait me donner (8,5), 12,76 devraient me donner (4,2), etc.
str code> ou
REC code>), mais ceux-ci échouent pour de grands nombres (bien que je comprends maintenant, ce sont les limites de la représentation de points flottante qui est le problème ici): p>
carte (len, rep. (Num) .split ('.')) Code> est le plus proche que je vais arriver à la précision et à l'échelle du flotteur? P> P>
9 Réponses :
Je pense que vous devriez envisager d'utiliser le Type Decimal au lieu d'un flotteur code>. Le type
float code> donnera des erreurs d'arrondi car les chiffres sont représentés en interne en binaire mais de nombreux nombres décimaux n'ont pas une représentation binaire exacte. P>
En gros, vous ne pouvez pas utiliser des chiffres de points flottants. à l'aide du type décimal aiderait et si vous voulez vraiment une grande précision, envisagez d'utiliser GMPY code> a >, le port de la bibliothèque de précision de GNU à Python. P>
Obtenir le nombre de chiffres à gauche du point décimal est facile:
import math def precision_and_scale(x): max_digits = 14 int_part = int(abs(x)) magnitude = 1 if int_part == 0 else int(math.log10(int_part)) + 1 if magnitude >= max_digits: return (magnitude, 0) frac_part = abs(x) - int_part multiplier = 10 ** (max_digits - magnitude) frac_digits = multiplier + int(multiplier * frac_part + 0.5) while frac_digits % 10 == 0: frac_digits /= 10 scale = int(math.log10(frac_digits)) return (magnitude + scale, scale)
Par curiosité, où vient le numéro 14? Est-ce indépendant de la plate-forme?
C'est une plate-forme dépendante, mais la plupart des plates-formes utiliseront IEEE-754. EN.Wikipedia.org/wiki/... aurait probablement pu faire Il 15, mais je voulais être conservateur et que mon arrondi fonctionnait correctement.
Au lieu d'avoir 14 codé dur, serait-il possible d'obtenir de la distribution de Python?
@aaragon Ce pourrait être possible, je ne sais pas. Étant donné que chaque version de Python que je connaisse est basée sur IEEE-754, je ne suis pas motivé pour le savoir.
@Aragon Curiosity a finalement eu le meilleur de moi, alors je l'ai regardé. Le numéro que vous recherchez est sys.float_info.dig code>
, qui est 15 sur ma version de Python.
(0) Veuillez confirmer ou refuser: vous avez des flotteurs à utiliser, il est inévitable, vous ne pouvez pas obtenir vos données comme décimale, les types de fichiers Oracle comprennent des types à base décimale et cette inadéquation fondamentale est inévitable. Veuillez expliquer tout déni complet ou partiel. p>
(1) Votre remarque "échec du grand nombre" est trompeuse / non pertinente / erronée - vous dites que votre point de départ est un flotteur, mais 1234567890.0987654321 ne peut pas être représenté comme un flotteur, comme le montre le résultat de la REP (). p>
(2) peut-être que vous pourriez peut-être utiliser la nouvelle REC (Python 2.7 et 3.1) qui fournit la précision minimale possible de REC (x) qui satisfait toujours E.g. Ancien REC (1.1) produit "1.1000000000000001", nouvelle REC (1.1) produit "1.1" p>
À propos de "Je suppose que la carte (len, rep. (Num) .split (". ') est le plus proche que je vais arriver à la précision et à l'échelle du flotteur? ": Vous avez besoin d'une stratégie pour gérer (A) Numéros négatifs et zéro (B) des nombres tels que creuser dans des objets / floatobject.c doit augmenter le code C pour la nouvelle REC () d'un objet flottant, si vous devez utiliser Python 2.6 ou antérieur. P>
(3) Peut-être que si vous nous avez dit les spécifications des types de données Oracle correspondants, nous pourrions vous aider à concevoir des contrôles pour choisir quel type peut contenir une valeur de flotteur donnée. P> float (REC (x)) == x code> p>
1.1e20 code> p>
0. Confirmer, essentiellement. Tout est configuré pour utiliser des flotteurs et je ne crois pas que CX_oracle traitera des types décimaux, au moins comme je l'ai mis en place. 1. édité pour corriger. 2. Intéressant, malheureusement je suis derrière 2,7. 3. J'essaie d'écrire du code qui fonctionnera dynamiquement même si les types de colonne Oracle changent de précision ou d'échelle. (Ouch, désolé pour le mauvais formatage)
impossible avec des variables à virgule flottante. Par exemple, la typing donne: p> donc, pour obtenir 6,4 sur ceci, vous devrez trouver un moyen de trouver un moyen Pour distinguer un utilisateur entrant 10.2345 code> et
10.234500000000001 code>, ce qui est impossible à l'aide de flotteurs. Cela a trait à la façon dont les numéros de points flottants sont stockés. Utilisez
décimal code>. P>
Est possible avec des flotteurs; voir ma réponse.
Ma réponse fonctionne aussi. La clé est de limiter le nombre de chiffres à la précision connue du type à flotteur et autour du résultat.
semble que str code> est meilleur choix que
REC code>:
Fonction Lambda pour trouver le nombre de chiffres à droite du décimal lambda x: len (str (x) .split (". ') [- 1]) Si len (str (x) .split ('. '))> 1 autre 0 code>
Si nous voulons retourner 0 pour 100,0 entrée lambda x: len (str (x) .split ('.') [- 1]) Si int (x)
En commençant par Python 3.2, il n'y a plus une différence entre REC code> et
str code> pour
float code> numéros. Voir Pourquoi Str (flotter) retourner plus de chiffres dans Python 3 que Python 2?
J'ai trouvé une autre solution qui semble être plus simple, mais je ne sais pas exactement si cela fonctionnera pour tous les cas.
import math x = 1.2345678 def flip(string): result = "" for ch in string: result = ch + result return result prec = int(math.log10(float(flip(str(x)))) + 1 # precision as int
Si vous devez vérifier la précision, vous pouvez essayer:
def prec_check(a,b) a = str(a) b = str(b) do = bool(True) n = 0 while do == True: if a and b and a[n] == a[b]: n += 1 else: do = false return n
Si vous devez vérifier le nombre de chiffres correspondants (d'A et B) Notez que cela ne fonctionne pas avec le module "décimal". p> p>