2014-09-07 4 views
0

Disons que j'ai un double a = 0.3;. Comment serais-je en mesure de changer l'exposant de la variable, sans utiliser les fonctions mathématiques comme pow(), ou en le multipliant manuellement.c change l'exposant d'un double

Je suppose que je devrais accéder aux adresses mémoire de la variable en utilisant des pointeurs, trouver l'exposant et le changer manuellement. Mais comment pourrais-je accomplir cela?

Notez que ceci est sur un système 8 bits, et je suis en train de trouver un moyen plus rapide de multiplier le nombre par 10^12, 10^9, 10^6 ou 10^3.

Meilleures salutations!

+2

Je ne pense pas que vous aurez beaucoup de succès. La partie exponentielle d'un point flottant typique est un exposant * binaire *, pas un dans la base 10. – unwind

+0

Voyant un ''double' 'est un nombre à virgule flottante * binaire, ajuster les bits de l'exposant n'aidera pas à multiplier par des puissances de dix, seulement par des puissances de deux. – delnan

+0

Avez-vous besoin d'un résultat précis, ou une approximation serait-elle suffisante pour vous? –

Répondre

2

Notez que a*10^3 = a*1000 = a*1024 - a*16 - a*8 = a*2^10 - a*2^4 - a*2^3.

Vous pouvez calculer a*10^3 comme suit:

  • Lire les 11 bits d'exposant dans int exp

  • Lire les 52 bits de fraction en double frac

  • Calculer double x avec exp+10 comme exposant et frac comme fraction

  • Calculer double y avec exp+4 comme exposant et frac comme fraction

  • Calculer double z avec exp+3 comme exposant et frac comme fraction

  • Calculer la sortie comme x-y-z, et ne pas oublier de ajouter le bit de signe si a < 0

Vous pouvez utiliser un similaire méthode r pour les autres options (a*10^6, a*10^9 et a*10^12) ...


Voici comment vous pouvez faire tout cela d'une manière "propre":

double MulBy1000(double a) 
{ 
    double x = a; 
    double y = a; 
    double z = a; 

    unsigned long long* px = (unsigned long long*)&x; 
    unsigned long long* py = (unsigned long long*)&y; 
    unsigned long long* pz = (unsigned long long*)&z; 

    *px += 10ULL << 52; 
    *py += 4ULL << 52; 
    *pz += 3ULL << 52; 

    return x - y - z; 
} 

S'il vous plaît noter que je Je ne suis pas sûr que ce code casse les règles d'alias strict.

+0

Un peu plus de travail est nécessaire avec 'frac' pour représenter le bit' 1' implicite quand l'exponent> minimum_exponent. – chux

+0

@chux: Je suis d'accord. Ceci est juste une idée générale, et j'ai laissé les détails de mise en œuvre spécifiques pour OP à traiter avec ... Merci. –

+0

a n'est jamais inférieur à 0. Alors, comment pourrais-je lire les bits d'exposant et de fraction? – user1806687

2

multipliant un nombre par 10 est l'équivalent de

  • a) en multipliant le nombre original de 2
  • b) en multipliant le nombre original de 8
  • c) ajouter les résultats de (a) et B).

Cela fonctionne car binaire est 1010. Une approche serait donc d'incrémenter l'exposant (pour (a)), d'ajouter 3 à l'exposant (pour (b)), puis d'ajouter les résultats.

Pour multiplier par 10^n, répétez les n fois ci-dessus. Vous pouvez également définir la représentation binaire de 1 000, 1 000 000, etc. et ajouter les 1 pertinents. Vous pouvez faciliter les choses en notant que 1000 par exemple 1024 (par exemple) est 1024-1016 - 8, à savoir

  • a) Ajouter 10 à l'exposant de l'original à multiplier par 1024
  • b) Ajouter C) Ajouter 3 à l'exposant de l'original à multiplier par 8
  • d) De (a) soustraire (b) et (c) pour obtenir la réponse.

Encore une fois, vous pouvez le faire plusieurs fois pour 10^6, 10^9 etc.

Pour une approximation rapide et puissances de n multiples de 3, ajoutez simplement 10N/3 à l'exposant (comme 1024 ~ = 1000)

1

Pour le plaisir, une solution récursive simple.

double ScalePower10(double x, unsigned power) { 
    if (power <= 1) { 
     if (power == 0) return x; 
     return x * 10.0; 
    } 
    double y = ScalePower10(x, power/2); 
    y = y*y; 
    if (power%2) y *= 10.0; 
    return y; 
    } 
+0

Salut Chux. Je pense que OP essaie (implicitement) d'éviter les opérations à virgule flottante. En plus de cela, bien que votre solution est générale pour tous les exposants possibles, je pense que OP demande une solution très spécifique ('a * 10^3',' a * 10^6', 'a * 10^9 'et' a * 10^12'). Compte tenu de ce fait, OP demande une solution optimisée, c'est-à-dire la meilleure performance pour le prix d'une solution non générique. –