Soyez le premier à donner votre avis sur cette source.
Vue 3 495 fois - Téléchargée 351 fois
// ---- fichier int128.hpp -- @author pgl10 ---- #ifndef INT128_HPP #define INT128_HPP #include <stdint.h> #include <string> class Int128 { public: ~Int128(); Int128(); Int128(int a); Int128(unsigned int a); Int128(int64_t a); Int128(uint64_t a); Int128(int64_t a, uint64_t b); Int128(const Int128& a); int64_t getHi() const; uint64_t getLo() const; void setHi(const int64_t a); void setLo(const uint64_t a); Int128 operator - () const; Int128 operator = (const Int128& a); Int128 operator += (const Int128& a); Int128 operator - (const Int128& a) const; Int128 operator -= (const Int128& a); Int128 operator *= (const Int128& a); Int128 operator / (const Int128& a) const; Int128 operator /= (const Int128& a); Int128 operator % (const Int128& a) const; Int128 operator %= (const Int128& a); Int128 operator ++ (); Int128 operator ++ (int); Int128 operator -- (); Int128 operator -- (int); int signe() const; std::string hexa() const; std::string deci() const; private: int64_t _hi; uint64_t _lo; }; Int128 operator + (const Int128& l, const Int128& r); Int128 operator - (const int& l, const Int128& r); Int128 operator * (const Int128& l, const Int128& r); bool operator == (const Int128& l, const Int128& r); bool operator != (const Int128& l, const Int128& r); std::ostream& operator << (std::ostream& ost, const Int128& v); int cmp128(const Int128& a, const Int128& b); Int128 pow128(const Int128& x, const int& n); int64_t toInt(const Int128& a); #endif // INT128_HPP // ---- fichier main.cpp -- @author pgl10 ---- #include <iostream> #include "int128.hpp" void main() { Int128 p, q; std::cout << std::endl << "n : p = 4^n+6*n-1 = 9*q" << std::endl << std::endl; for(int n=0; n<64; n++) { p = pow128(4,n) + 6*n - 1; q = p / 9; if(p == 9*q) std::cout << n << " : " << p << " = 9*" << q << std::endl; } std::cout << std::endl << std::endl; }
Il me semble que votre programme ci-dessus montre bien que votre union U64 permet de faire les calculs sur les entiers de 64 bits comme vous le souhaitez pour les valeurs positives. Mais que se passe-t-il pour les nombres négatifs avec cette représentation ? Pour cette raison, dans Int128 je représente un entier 128 bits par un int64_t (signé) et un uint64_t. Si les int64_t ont rendu obsolète votre ancien développement à base de U64, il en sera de même pour Int128 parce que les int128_t arrivent déjà avec certains compilateurs mais pas tous actuellement. Le mien : Visual Studio 2012 Express for Windows Desktop en français ne les a pas. Si vous souhaitez développer votre solution à base de l'union U128 pour les entiers positifs sur 128 bits cela devrait fonctionner. Je ne sais pas si vous souhaitez traiter aussi les nombres entiers négatifs sur 128 bits. Si oui, quelle sera la représentation du signe ? D'autres avis éventuels sont les bienvenus.
Merci pour votre réponse.
J'espère ne pas "abuser" en me permettant de présenter une autre "idée":
Il y a bien longtemps, lorsque les nombres sur 64 bits n'étaient qu'un rêve, j'avais fait des routines pour simuler ces "immenses" entiers.
Malheureusement, devenu inutile par la suite, je n'en ai pas gardé les sources.
Je me souviens seulement que j'avais utilisé la notion union de C, qui devait correspondre à:
Cela me permettait d'écrire les routines d'addition, de multiplication, etc, sans "encombrer" les codes de shifts, de masques et d'opérations binaires.
Dans le code qui suit, j'ai ajouté à la fin dans l'union
uint64_t u64
pour pouvoir "vérifier" (aujourd'hui, en 64 bits) certaines valeurs:
Pour laisser au compilateur les opérations "obscures" sur les bits, pourrait-on d'une manière analogue simuler les entiers de 128 bits en utilisant:
?
Merci d'avance pour votre avis.
Bonne continuation ...
Je suis admiratif pour cet examen très attentif. J'ai donc compté, moi aussi, le nombre de multiplications effectuées dans la fonction dix() pendant le test de Int128 et j'ai trouvé moi aussi 94848. J'ai aussi compté le nombre de fois où dix() a été appelée et j'ai trouvé 4992. En effet cette fonction est appelée plusieurs fois pendant l'exécution de decistr(). Ce qui montre que dix(int n){} qui calcule 10^n effectue bien, comme attendu, n multiplications à chaque appel. C'est pourquoi je retiens la nouvelle version modifiée de dix() comme vous l'avez proposée : elle est plus performante. Merci pour ce commentaire et cette amélioration.
En parcourant le code source que vous proposez, mon attention a été attirée par la fonction:
qui n'est utilisée que dans Int128::decistr(), c'est-à-dire pour la "transformation en décimales".
En comptant le nombre de multiplications x = x * 10 qui y sont calculées lors du test, j'arrive à 94848 !
Pourquoi ne pas appliquer le même algorithme que vous utilisez plus bas:
Ce qui pourrait donner:
En utilisant cette fonction, le nombre de multiplications est réduit à 24448 !
Ce qui me semble toujours énorme !
Comme la fonction dix(n) est toujours utilisée avec (0 <= n <= 38), on peut réduire ce nombre de multiplications à zéro (ou 38), en donnant un tableau de 39 valeurs précalculées (*).
(*) Remarque sur la "météo": attention à l'orage !
En ce qui concerne l'algorithme utilisé dans Int128 pow128(Int128 x, int n), je ne le connaissais pas et il semble être plus efficace que l'algorithme le plus souvent proposé:
En effet, votre test effectue 513 multiplications avec la fonction ci-dessus, alors qu'avec celle que vous proposez, il n'en calcule que 387 !
Merci pour vos apports et votre fair-play.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.