C'est clair que c'est plus simple que Vigenère !
A propos, je viens à l'instant d'envoyer avec 24h de retard ma solution pour l'exercice de décembre 2008... Elle dormait dans un de mes dossiers depuis presque 1 mois maintenant
Nanoc, tu as reçu combien de réponses ?
Inkamath on GitHub - Interpréteur d'expressions mathématiques. Reprise du développement en cours.
Maintenant que tu le dis, j'avais fait le chiffrement et le déchiffrement sous toutes ses formes, mais j'ai complètement oublié de faire le reste, tant pis pour cette fois.
Je test le problème 1 du projetEuler et la Oh surprise!Mon programme trouve la bonne réponse pour 10,mais quand,fièrement je met 1000,il ne trouve pas la bonne réponse...bon,j'ai utilisé une méthode bourine mais clair a mes yeux.
Donc voici mon prgramme:
#include <iostream>
using namespace std;
int main()
{
for(;;) {
int nbMax = 1000, nbMultiple = 0,i=0,resultat=0;
cout << "nombre Max:" ;
cin >> nbMax;
//cout << endl << "multiple de 5:" << endl;
// nombre de multiple de 5
for(i=0;;i++) {
resultat = 5*i;
if (resultat < nbMax) {
nbMultiple += resultat;
//cout << ","<< resultat;
}
else break;
}
//cout << endl <<"multiple de 3:" << endl;
//nombre de multiple de 3
resultat = 0;
for(i=0;;i++) {
resultat = 3*i;
if (resultat < nbMax) {
nbMultiple += resultat;
//cout << ","<< resultat;
}
else break;
}
cout << endl << nbMultiple << endl;
}
return EXIT_SUCCESS;
}
Merci d'avance si vous pouvez m'éclairer.
EDIT:Desolé si le post est HS,mais merci pour la réponse aussi^^
@Dam60 : car avec ta méthode tu comptes deux fois certains nombre comme 15 (3*5), ou 30 (3*2*5), d'après ce que je comprends l'idéal serait de faire un test if avec un ou et des modulos if( ((lenombre%3)==0) || ((lenombre%5)==0))
Bonjour tout le monde ! Il est temps que je dévoile une solution pour l'exercice du mois de décembre. Vous avez été 8 à m'envoyer une solution.
Tous les codes reçus fonctionnaient (C'est la première fois !) et parmi ces réponses, je vous propose la solution de iNaKoll qui est le seul à avoir réussi à décoder le texte donné.
Voici la description de son programme ainsi que son code commenté.
Définition (cahier des charges)
But du programme :
- Niveau 1 : chiffrer et déchiffrer un message entré par l'utilisateur à l'aide du chiffre de Vigenère et d'une clé entrée par l'utilisateur
- Niveau 2 : connaissant la taille de la clé, il s'agit de cryptanalyser le message codé afin de déterminer la clé
- Niveau 3 : cryptanalyser le message codé afin de trouver la taille de la clé et se ramener au niveau 2 pour déterminer la clé
- Laisser la possibilité à l'utilisateur de choisir un fichier d'entrée et/ou un fichier de sortie
Structure du programme en 3 parties
1) Entrées/sorties ("parsage" de la ligne de commande, entrées/sorties avec les fichiers)
2) Traitement des données (cryptage, décryptage et/ou cryptanalyse)
3) Programme principal
1) Entrées/sorties
Afin de réaliser cet exercice, je me suis très fortement inspiré de la gestion des paramètres de la ligne de commande qu'a réalisé Chlab_lak pour l'exercice précédent. J'ai cependant apporté quelques petites améliorations ici et là...
Sans plus attendre : clo.h
#ifndef H_CLOPTION
#define H_CLOPTION
#include <iostream> //std::cout
#include <cstdlib> // strtol
#include <fstream> // std::ifstream, std::ofstream
#include <sstream> // std::ostringstream
#include <string> // std::string
#include <stdexcept> // std::logic_error, std::runtime_error
class CLO
{
public:
/* Constructor */
CLO(int argc, char *argv[])
: options_flags(0)
{
std::string Buf;
for(int i = 1; i < argc;)
{
Buf = argv[i];
/* Input File*/
if(Buf == "-i")
{
input = ""; // on ignore toute autre entree precedante
if(Flag(INPUT_FILE))
throw std::logic_error(
"Le parametre -i a ete trouve plusieurs fois.");
if(i+1 < argc && argv[i+1][0] != '-')
input=LoadFromFile(argv[++i]);
else
throw std::logic_error(
"Le nom du fichier d'entree est manquant.");
options_flags |= INPUT_FILE;
}
/* Output File */
if(Buf == "-o")
{
if(Flag(OUTPUT_FILE))
throw std::logic_error(
"Le parametre -o a ete trouve plusieurs fois.");
if(i+1 < argc && argv[i+1][0] != '-')
output_filename = argv[++i];
else
throw std::logic_error(
"Le nom du fichier de sortie est manquant.");
options_flags |= OUTPUT_FILE;
}
/* CRYPTER */
else if(Buf == "-c")
{
if(Flag(CRYPTER) || Flag(DECRYPTER))
throw std::logic_error(
"Les parametres -c et/ou -d ont ete trouves plusieurs fois.");
if(i+1 < argc && argv[i+1][0] != '-')
cle = argv[++i];
else
throw std::logic_error(
"La cle de cryptage est manquante.");
options_flags |= CRYPTER;
}
/* DECRYPTER */
else if(Buf == "-d")
{
if(Flag(CRYPTER) || Flag(DECRYPTER))
throw std::logic_error(
"Les parametres -c et/ou -d ont ete trouves plusieurs fois.");
if((i+1 < argc) && (argv[i+1][0] != '-'))
{
char* endptr = 0;
long size = strtol(argv[++i],&endptr,10);
if(endptr!=argv[i] && size != 0)
{
cle.resize(size,0);
std::cout << "Taille de la cle de decryptage connue : ";
std::cout << "cryptanalyse des donnees et deduction de la cle." << std::endl;
}
else
cle = argv[i];
}
else
{
std::cout << "Cle de decryptage et taille inconnue : ";
std::cout << "cryptanalyse des donnees et deduction de la cle." << std::endl;
}
options_flags |= DECRYPTER;
}
else if(Buf == "-v")
{
options_flags |= VERBOSE;
}
else if(Buf == "-h")
{
options_flags |= AIDE;
}
/* Append to input */
else if(!Flag(INPUT_FILE))
input += Buf;
++i;
}
/* Check */
if(input.empty())
throw std::logic_error("Le parametre chaine n'a pas ete trouve.");
if((options_flags & CRYPTER == 0) && (options_flags & DECRYPTER == 0))
throw std::logic_error("Aucun parametre -c ou -d trouve.");
}
const std::string &Input(void) const
{
return input;
}
const std::string &Cle(void) const
{
return cle;
}
const std::string &OutputFilename(void) const
{
return output_filename;
}
unsigned int GetFlags(void) const
{
return options_flags;
}
bool Flag(const int f)
{
return ((options_flags & f) != 0);
}
std::string LoadFromFile(const std::string &Name)
{
std::ifstream Ifs(Name.c_str());
if(!Ifs)
throw std::runtime_error(
"Impossible d'ouvrir le fichier en lecture");
std::ostringstream Oss;
Oss << Ifs.rdbuf();
return Oss.str();
}
/* Save in a file */
void SaveInFile(const std::string &Name, const std::string &String)
{
std::ofstream Ofs(Name.c_str());
if(!Ofs)
throw std::runtime_error("Impossible d'ouvrir le fichier en ecriture");
Ofs << String;
}
static const int CRYPTER ;
static const int DECRYPTER;
static const int AIDE;
static const int INPUT_FILE;
static const int OUTPUT_FILE;
static const int VERBOSE;
private:
std::string input;
std::string cle;
std::string output_filename;
unsigned int options_flags;
};
const int CLO::CRYPTER = 1;
const int CLO::DECRYPTER = 2;
const int CLO::AIDE = 4;
const int CLO::INPUT_FILE = 8;
const int CLO::OUTPUT_FILE = 16;
const int CLO::VERBOSE = 32;
#endif
2) Traitement des données
Sans aucun doute la partie la plus importante !
Fonction crypter :
void vigenere_crypter(const string& input, string& output, const string& cle)
{
output.resize(input.size(),0);
for(size_t i=0,j=0; i!=input.size(); ++i)
{
if(j==cle.size()) j = 0;
output[i] = toupper(input[i]);
//if(isupper(output[i])) /* L'utilisation de la fonction isupper ici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
if((output[i] >= 'A') && (output[i] <='Z'))
{
output[i] = ((output[i] + cle[j]-2*'A') % 26 + 'A');
++j;
}
else
{
output[i] = input[i];
}
}
}
Cette fonction prend en paramètres des références sur le message à crypter (input), le message crypté (output) ainsi que sur la clé de cryptage.
La fonction est simple :
1) initialisation du message crypté avec le message en clair
2) mise en majuscule du message crypté
3) substitution des lettres du message par leur équivalent crypté (les autres caractères sont inchangés).
Fonction décrypter :
void vigenere_decrypter(const string& input, string& output, string& cle)
{
// Si on ne connait pas la clé
if((cle.size() == 0) || (cle[0] == 0))
{
// on la détermine par cryptanalyse
vigenere_cryptanalyse(input,output,cle);
}
string cle_tmp = cle;
for(size_t j=0; j!=cle_tmp.size(); ++j)
{
cle_tmp[j]= 26-(cle_tmp[j] - 'A') + 'A';
}
vigenere_crypter(input,output,cle_tmp);
}
Si l'on n'a aucune information sur la clé alors cle.size()==0
Si on ne connait que la taille de la clé alors cle.size() renvoie la taille de la clé. La clé étant en elle même inconnue, on aura au préalable initialisé la string cle avec les caractères '\0'. Ceci explique donc le test cle[0]==0 en début de fonction.
Dans ces deux cas, on cryptanalyse le message pour déterminer la clé, c'est le travail de la fonction vigenere_cryptanalyser.
Enfin, une fois la clé connue, on réutilise le code de la fonction vigenere_crypter pour déchiffrer le message.
Fonction cryptanalyser :
void vigenere_cryptanalyse(const string& input, string& output, string& cle)
{
// Si la taille de la clé n'a pas été donnée, on la calcule
if(cle.size() == 0)
cle.resize(calculer_longueur_cle(input),0);
// On fait une analyse de frequence pour trouver la clé
size_t taille_donnees = 0;
vector<vector<int> > freqs_input = calculer_frequences(input,taille_donnees,cle.size());
for(size_t i=0; i<cle.size(); ++i)
{
/* Methode 1 : décalage par rapport à la plus grande frequence (lettre 'E')*/
//cle[i]=(max_element(freqs_input[i].begin(),freqs_input[i].end())-freqs_input[i].begin()-'E'+'A')%26+'A');
/* Methode 2 : moindres carrés par rapport au spectre de la langue */
vector<double> normes;
for(size_t j=0;j<26;++j)
{
vector<double> diff;
rotate_copy(freqs_input[i].begin(),freqs_input[i].begin()+j,freqs_input[i].end(),std::back_inserter(diff));
transform(diff.begin(),diff.end(),diff.begin(),bind2nd(divides<double>(),taille_donnees));
transform(diff.begin(),diff.end(),fr_freqs,diff.begin(),minus<double>());
transform(diff.begin(),diff.end(),diff.begin(),diff.begin(),multiplies<double>());
normes.push_back(accumulate(diff.begin(),diff.end(),0.0,plus<double>()));
}
cle[i]=min_element(normes.begin(),normes.end())-normes.begin()+'A';
}
}
Si la taille de la clé est inconnu, on demande à la fonction calculer_longueur_cle de la calculer pour nous.
Une fois la taille connue, on procède à une analyse de fréquences comme pour le chiffre de César afin de déterminer la clé. Je propose deux méthodes de résolution :
1ère méthode : La lettre la plus fréquemment rencontrée dans le message est considérée comme étant un 'E' ce qui permet de déterminer le décalage.
2ème méthode - moindres carrés : on cherche à minimiser la somme des carrés des différences entre les fréquences de références de la langue française et les fréquences observées dans le message. L'erreur minimum est obtenue pour un décalage correspondant à la clé de cryptage.
Fonction calculer_longueur_cle :
size_t calculer_longueur_cle(const string& input)
{
// pour chaque longueur de clé possible
size_t taille_cle=0;
double ic=0;
do
{
++taille_cle;
size_t taille_donnees = 0;
vector<vector<int> > freqs = calculer_frequences(input,taille_donnees,taille_cle); // on fait une analyse de frequence
ic=calculer_ic(freqs,taille_donnees,taille_cle); // on calcule l'indice de coincidence
}while(taille_cle<input.size() && !is_ic_cible(ic));
// On a trouvé la longueur de la clé
return taille_cle;
}
Cette fonction calcule pour chaque longueur de clé possible l'indice de coïncidence du message.
Dés qu'un indice de coïncidence proche de celui de la langue française est trouvé, on sait que la longueur de clé actuellement testée est fortement probable et on renvoie cette valeur.
Fonction d'analyse fréquencielle :
vector<vector<int> > calculer_frequences(const string& input, size_t& taille_donnees, size_t taille_cle)
{
taille_donnees = 0;
string tmp(input.size(),0);
vector<vector<int> > freqs(taille_cle, vector<int>(26,0)); // pour chaque caractère de la clé on a 26 fréquences
for(size_t i=0; i!=input.size(); ++i)
{
tmp[i] = toupper(input[i]);
//if(isupper(tmp[i])) /* L'utilisation de la fonction isupperici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
if((tmp[i] >= 'A') && (tmp[i] <= 'Z'))
{
++freqs[taille_donnees%(taille_cle)][tmp[i]-'A'];
++taille_donnees;
}
}
taille_donnees/=taille_cle;
return freqs;
}
Cette fonction calcule pour chaque longueur possible de la clé la fréquence d'apparition des lettres.
Elle est utilisé pour le calcul de l'indice de coïncidence et pour le calcul du décalage de la clé une fois la taille de celle-ci connue.
Cette fonction permet de calculer l'indice de coïncidence d'un message à partir de son spectre de fréquences (fonction calculer_frequences).
Fonction is_ic_cible :
// renvoie true si 'ic' est proche de 'ic_cible' à 'prec' pourcents près
bool is_ic_cible(double ic, double ic_cible, double prec)
{
return prec*ic_cible>fabs(ic-ic_cible) || ic>ic_cible;
}
Cette fonction renvoie vrai si l'indice de coïncidence passé en paramètre est proche de l'indice de coïncidence de la langue.
Après quelques essais, je me suis rendu compte qu'un indice de coïncidence élevé bien que très différent de l'indice de coïncidence de référence donne généralement de bons résultats pour le calcul de la longueur de la clé. Ainsi, cette fonction valide tout indice de coïncidence supérieur à l'indice de coïncidence de référence.
Le code complet de la partie traitement :
vigenere.h
Pour finir voici une petite aide pour l'utilisation du programme :
AIDE
> Synopsis : vigenere {[-i] _input_} {{-c _cle_ }|{-d [_cle_]|[_taille_cle_]}} [-o _output_]
> _input_ : chaine de caractere a traiter, a entourer d'apostrophes si possible
> -i : Indique que _input_ est le nom du fichier a traiter
> -o : Permet d'indiquer que _output_ est le fichier de sortie
> -c : Chiffre le texte de _input_ avec _cle_
> -d : Dechiffre le texte de _input_ avec _cle_ ou par cryptanalyse avec ou sans _taille_cle_
Exemples :
Niveau 1 :
E:\cpp\vigenere2>vigenere "JOYEUX NOEL LES ZEROS" -c SDZ -v
Cryptage...
Taille de la cle : 3
Cle : SDZ
Output : BRXWXW FRDD ODK CDJRR
E:\cpp\vigenere2>vigenere "BRXWXW FRDD ODK CDJRR" -d SDZ -v
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output : JOYEUX NOEL LES ZEROS
Ici on crypte (-c) et on décrypte (-d) un message à l'aide de la clé "SDZ".
En absence de fichier de sortie, il est recommandé d'utiliser le mode verbose (-v) afin d'afficher les données traitées (Output).
Niveau 2 :
E:\cpp\vigenere2>vigenere -i aide.txt -c SDZ -v -o aide_c.txt
Cryptage...
Sauvegarde effectuee dans : aide_c.txt.
Taille de la cle : 3
Cle : SDZ
Output :
SLCW
> VXFROKLR : NLFWQDJH {[-H] _AQOMW_} {{-B _UOD_ }|{-V [_FKW_]|[_WZAOKW_FKW_]}} [-R _NMWOMW_]
> _HFSTL_ : FGSLMW GD UDQSFSWUD S WQSLSWU, Z WQSGXQWU C'SSNKWQGSGWV RA SNKVHTOD
> -A : LMVLPMH PMH _HFSTL_ HRL OD FRL VX EAFGAHQ S WQSLSWU
> -N : HHQEHS V'LMVLPMHQ IXD _GXSHXS_ WVS DH EAFGAHQ VH RGUSAH
> -B : UKHXIQW OD LHWLH CW _LMHXS_ SYDU _FKW_
> -G : CWFGAIEJH KW WDPWD VH _HFSTL_ DUWF _BDH_ NM SZJ FQQSSSQZDBRW DUWF NM VZFV _SSLKDH_BDH_
E:\cpp\vigenere2>vigenere -i aide_c.txt -d 3 -v
Taille de la cle de decryptage connue : cryptanalyse des donnees et deduction de la cle.
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output :
AIDE
> SYNOPSIS : VIGENERE {[-I] _INPUT_} {{-C _CLE_ }|{-D [_CLE_]|[_TAILLE_CLE_]}} [-O _OUTPUT_]
> _INPUT_ : CHAINE DE CARACTERE A TRAITER, A ENTOURER D'APOSTROPHES SI POSSIBLE
> -I : INDIQUE QUE _INPUT_ EST LE NOM DU FICHIER A TRAITER
> -O : PERMET D'INDIQUER QUE _OUTPUT_ EST LE FICHIER DE SORTIE
> -C : CHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_
> -D : DECHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_ OU PAR CRYPTANALYSE AVEC OU SANS _TAILLE_CLE_
Cette fois, le message a traiter est contenu dans le fichier indiqué après l'option '-i'.
Les données de sorties (Output) sont sauvegardées dans un fichier en plus d'être affichées dans la console en mode verbose.
Dans un premier temps, on crypte le fichier "aide.txt" avec la clé "SDZ" le resultat est enregistré dans le fichier "aide_c.txt" et est affiché dans la console. Le fichier "aide_c.txt" est ensuite décrypté en donnant au programme la taille de la clé utilisée pour le cryptage (3). La clé est déduite et affichée dans la console par le programme.
Niveau 3 :
E:\cpp\vigenere2>vigenere -i aide_c.txt -d -v
Cle de decryptage et taille inconnue : cryptanalyse des donnees et deduction de la cle.
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output :
AIDE
> SYNOPSIS : VIGENERE {[-I] _INPUT_} {{-C _CLE_ }|{-D [_CLE_]|[_TAILLE_CLE_]}} [-O _OUTPUT_]
> _INPUT_ : CHAINE DE CARACTERE A TRAITER, A ENTOURER D'APOSTROPHES SI POSSIBLE
> -I : INDIQUE QUE _INPUT_ EST LE NOM DU FICHIER A TRAITER
> -O : PERMET D'INDIQUER QUE _OUTPUT_ EST LE FICHIER DE SORTIE
> -C : CHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_
> -D : DECHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_ OU PAR CRYPTANALYSE AVEC OU SANS _TAILLE_CLE_
Cette fois le fichier "aide_c.txt" est décrypté par le programme sans que celui-ci ne connaisse la clé utilisée pour le cryptage. La clé est déduite et affichée dans la console par le programme.
Enfin, voici ce que donne le programme pour le texte crypté du niveau 3 :
Effectivement, j'ai bien fait de m'arrêter au niveau 1.
J'aurais jamais eu le temps à consacrer pour étudier comme il faut l'analyse fréquentielle et en faire un algorithme qui tourne avec la table de Vigenere.
Toutefois, je vais prendre le temps de lire ça en détail, ça m'instruira
Surtout qu'il semble y avoir pas mal de STL que je connais pas
Bravo au gagnant, et merci à Nanoc pour sa patience
edit : effectivement, j'étais jamais retourné sur http://www.sgi.com/. Comme je suis plus apte qu'avant à comprendre tout ça, je vais pouvoir me régaler
Disons que la version de iNaKoll est vraiment une version "de luxe". Il a vraiment poussé à fond le coté cryptanalyse et cheerché un moyen de réaliser le craquage de manière générique.
Du coté du code il a énormément utilisé la STL, ce qui est bien, mais comme toujours non obligatoire. Connaître la STL de fond en comble n'est pas nécessaire pour réussir ces exercices.
Savoir qu'il existe une fonction "find" est très bien, mais pas essentiel, si on ne le savait pas, on peut la reocer sois-même sans problème. Même si ça sera légèrement moins efficace.
Salut, je suis nouveau dans les exos de Nanoc, pour envoyer son pogramme à Reponse_Exercice on fait comment, on envoie par mail sur nanoc.sdz@gmail.com ??
Nom : Chiffres romains Sujet : algorithmes, chaînes de caractères
Avant de repartir dans la cryptographie, il était temps d'avoir un exercice plus simple.
Vous connaissez certainement les chiffres romains et vous savez certainement que lorsqu'on a pas l'habitude de les utiliser, lire ou écrire un de ces nombres peu être fastidieux.
L'exerice de ce mois va justement résoudre ce problème en vous permettant de réaliser un traducteur chiffres arabes <-> chiffres romains.
Que sont les chiffres romains ?
Les romains utilisaient un système différent du notre pour représenter les chiffres. Ils utilisaient les principes suivants:
Les règles à utiliser varient selon les sources. Pour cet exercice, on prendra les règles précisées ci-dessous.
On utilise les symboles suivants:
I = 1
V = 5
X = 10
L = 50
C = 100
D = 500
M = 1000
Règle 1: On arrange ensuite les symboles dans l'ordre décroissant pour former un nombre qui sera lu en additionnant chacune des symboles.
Par exemple 26 peut s'écrire comme XXVI ou XXIIIIII ou encore XVVVI. La première version étant préférée car utilisant moins de symboles.
Règle 2: On peut utilise des soustractions en plaçant un (et uniquement un) symbole de petite valeur juste avant un symbole de plus grande valeur. Le résultat de cette manipulation est alors la différence entre le symbole le plus grand et le plus petit.
Exemple: IV = 5-1 = 4 ou bien CIX = 100 + 10 - 1 = 109
Règle 3: La soustraction ne peut se faire qu'avec les symboles suivants:
I devant V ou X
X devant L ou C
C devant D ou M
Ceci implique que 49 n'est pas IL mais XLIX
Règle 4: Il n'y a pas de nombres plus grands que 4999 dans ce système, ni de nombres plus petits que 1.
Règle 5: On utilise toujours la combinaison de symboles la plus courte.
Donc XXVI au lieu de XVVVI, mais XLIX au lieu de IL sinon on viole la règle 3.
L'exercice
Niveau 1
Comme vous pouvez vous en douter, votre programme devra "traduire" un nombre entier en chiffre romain (valide) et afficher le résultat dans la console.
Il devra également pouvoir traduire les chiffres romains sous forme de strings en nombres entiers.
Si un nombre est non-valide, le programme devra afficher un message d'erreur.
Entrez un nombre romain: XXVII
Votre nombre est: 27
Entrez un chiffre romain: DDXI
Votre chiffre est non-valide
...
Niveau 2
Si le nombre romain entré par l'utilisateur est non-valide, votre programme devra indiquer quelle règle est violée et proposer (si possible) une correction.
Entrez un nombre romain: XXXXI
Votre chiffre est non-valide. Il viole la règle 5: On peut l'écrire de manière plus courte.
Le résultat serait: XLI
Ce qui donne en chiffres arabes: 41
N'hésitez pas à poser des questions si vous en avez !
Vous avez jusqu'au 15 mars pour soumettre vos réponses à Réponse_Exercices.
Bonne chance à tous !
EDIT: Suppression du 0 pour éviter les ambiguités.
C'est vraiment une très bonne initiative de proposer des exercices, merci à toi !
Edit : je ne suis pas sur (c'est ne primaire qu'on voit les chiffre romains donc...), mais je crois que le 0 n'existe pas en chiffres romains... à confirmer.
Même si ce n'était pas aberrant comme méthode ce n'est pas possible parce que le but c'est de traduire le romain en arabe. Donc ça ne passerait pas dans un switch. (une suite de else if peut-être ... )
On a le droit de faire un switch avec tous les cas possibles ??
switch (nombre)
{
case 1:
return I
break;
case 2:
return II
break;
case 3:
return III
break;
case 4:
return IV
break;
}
Disons que si tu me sors un code en méta-programmation qui fait l'équivalent de ton switch pourquoi pas.
C'est quoi la... méta-programmation ? J'ai cherché sur Wikipédia et j'ai rien pigé
</hs>
Sinon, comment on doit implémenter le concept du 0 ? Parce que j'ai codé une petite fonction, mais je suis pas sur que c'est le but recherché .
Enfin, voilà comment je procède :
Citation : Mon implémentation du 0
On a une partie du chiffre convertit en chiffres arabes, et on rajoute un zéro à sa suite (on multiplie par 10... j'y pense, j'ai fait une vingtaine de lignes alors que j'ai juste à multiplier par 10 *cours se suicider pour son intelligence bornée*)
Bon, sérieusement, un exemple :
Étant donné le chiffre romain MDLXO, on commence à le mettre en chiffre arabes... 1000 + 500 + 50 + 10 = 1560... et le O, donc on rajoute un 0 = 15'600.
C'est ça ? (bon, ici, ce n'est pas valide puisque le maximum est 4999 enfin, c'est un exemple )
Voilà, j'ai fini mes questions, je vais virer mes lignes de codes en trop et remplacer par une multiplication par 10
Non.. ou enfin, comme je l'ai compris, ce n'est pas ça.
Chaque symbole romain avait une valeur, mais, par exemple, II, ce n'est pas 11 mais 1 + 1 soit 2.
O, c'est donc un caractère qui a 0 comme valeur, soit MDLXO vaut la même chose que MDLX et donc que MDLXO n'est pas valide (puisqu'il y a une façon plus courte de l'écrire).
O représenterait donc tout simplement le nombre 0!...
Mais le nombre 0 n'existe pas chez les romains... ou alors, on ne pourrais l'utiliser que si on met 0... donc, O ne sert à rien... j'ai rien pigé ! (tant pis, je garde ma solution de * 10 en attendant que Nanoc revienne pour donner des précisions quand à ce petit problème )
Non.. ou enfin, comme je l'ai compris, ce n'est pas ça.
Chaque symbole romain avait une valeur, mais, par exemple, II, ce n'est pas 11 mais 1 + 1 soit 2.
O, c'est donc un caractère qui a 0 comme valeur, soit MDLXO vaut la même chose que MDLX et donc que MDLXO n'est pas valide (puisqu'il y a une façon plus courte de l'écrire).
O représenterait donc tout simplement le nombre 0!...
Correct !
Citation : Cyprien_
Amha, tu devrais virer le zéro Nanoc, il n'existait pas chez les Romains, et ça embrouille presque plus qu'autre chose .
Mouais. Je pensais pas que ça embrouillerait mais vous m'avez convaincu. J'enlève.
disons que dans ce cas-là le O sert seulement à représenter 0 et uniquement cette valeur. Elle n'intervient nulle part ailleurs. C'est ce qui tend à "déstabiliser" les gens.