Je sais que vous pouvez utiliser cette table pour convertir décimale en BCD: P>
0 0000 p>
1 0001 p>
2 0010 P>
3 0011 P>
4 0100 P>
5 0101 P>
6 0110 P>
7 0111 P>
8 1000 p>
9 1001 P>
Y a-t-il une équation pour cette conversion ou vous devez simplement utiliser la table? J'essaie d'écrire du code pour cette conversion, mais je ne sais pas comment faire les mathématiques pour cela. Suggestions? P>
10 Réponses :
Vous connaissez le Système de chiffres binaires , n'est-ce pas?
surtout a Regardez Ce chapitre . P>
Edit: Notez également le commentaire de KFRO Les nibiles inférieurs (= 4 bits) de la représentation binaire ASCII de chiffres sont en BCD. Cela fait des conversions BCD <-> ASCII très faciles comme il vous suffit d'ajouter / supprimer les 4 bits principaux: p>
Il convient également de noter que les représentations ASCII pour les chiffres sont également en BCD (exprès) ... au moins au moins le nybble inférieur.
Er ... kfro. Ce n'est pas terriblement clair. Voulez-vous dire que le grignotage inférieur de la représentation ASCII pour les chiffres correspond à la représentation de la BCD du chiffre?
@DMCKEE: C'est le cas, alors je suppose que c'est ce que Kfro signifiait: "0" code> est
0x30 code>,
"1" code> est
0x31 code> etc.
Les chiffres d'ASCII ne sont pas équivalents BCD, mais EBCDIC sont. IE: Les 1er 10 entrées de la table EBCDIC sont les chiffres de la BCD 0-9 où le nibble le plus significatif est de 0B0000, tandis que dans ASCII, ils sont décalés hexagonaux 30, à savoir: ASCII '0' == 0x30 dans la table ASCII.
@RockeTroy qui n'est pas vrai. Les entrées EBCDIC pour les chiffres sont dans la plage 0xf0 code> à
0xf9 code>.
@Fuzxxl, je suis corrigé. Vous avez raison. 0xf0 à 0xf9 c'est! La question est si mal spécifiée, je ne peux pas dire ce que l'OP demande, mais si l'ASCII à BCD soustrait Sous-trayez 0x30 sur le char et appuyez sur les 4 derniers bits dans un tampon jusqu'à ce que vous manquiez de chiffres. Une bonne façon de le faire est d'utiliser '0' au lieu de 0x30. Il est plus facile de comprendre ce qui est fait quand quelqu'un d'autre lit votre code 5 ans plus tard et que vous êtes parti depuis longtemps. Cette réponse n'est pas très utile. Code pour pousser deux nybbles sur un char et ensuite concaténer des caractères dans une "chaîne" fonctionne bien et est propre.
quelque chose comme ce travail pour votre conversion?
généralement lorsque quelqu'un dit qu'ils veulent convertir de la décimale en BCD, ils parlent de plus d'un chiffre décimal.
BCD est souvent emballé dans deux chiffres décimaux par octet (car 0..9 ajustement en 4 bits , comme vous l'avez montré), mais je pense qu'il est plus naturel d'utiliser une gamme d'octets, un par chiffre décimal. p>
Un nombre binaire non signé N-bits s'intégrera au CEIL (n * log_2 (10 )) = CEIL (n / log10 (2)) chiffres décimaux. Il conviendra également au CEIL (N / 3) = plancher ((N + 2) / 3)) chiffres décimaux, car 2 ^ 3 = 8 est inférieur à 10. P>
avec cela à l'esprit, voici Comment j'aurais obtenu les chiffres décimaux d'un INT non signé: p> bien sûr, si vous connaissez la largeur de votre type INT, vous préférez préférer des tableaux de longueur fixe. Il n'y a pas non plus de raison d'inverser du tout si vous pouvez vous rappeler que le 0ème chiffre est le moins significatif et inverse uniquement sur l'entrée / la sortie. Garder le chiffre le moins important comme le premier simplifie les OP arithmétiques du chiffre-sage dans le cas où vous n'utilisez pas un nombre fixe de chiffres. P> si vous voulez représenter "0" comme le "0" unique. chiffre décimal plutôt que la chaîne de chiffre vide (soit valide), vous vérifiez spécifiquement spécifiquement pour x == 0. p> p>
BCD utilisant uniquement le nybble de fin dans un octet est très inefficace. MySQL a abandonné cette approche il y a des années, et plus récemment, BCD entièrement pour des données décimales. Vous pouvez facilement quitter le changement de Nybble d'un octet de tête autrement gaspillé. Ensuite, il suffit de concaténer le double nybble / octet / char à un tableau de caractères. Simple, efficace, simple.
Si vous voulez deux chiffres décimaux par octet et "non signé" est la moitié de la taille de "non signé long" (utilisez uint32 et uint64 TypeDefs si vous le souhaitez):
unsigned long bcd(unsigned x) { unsigned long ret=0; while(x>0) { unsigned d=x/10; ret=(ret<<4)|(x-d*10); x=d; } return ret; }
Cela se tient du monde du micro-contrôleur ... Notez que les valeurs sont arrondies dans la division. Par exemple, 91 à BCD serait 91/10 * 16 = 144 + 91% 10 = 145. Converti en binaire est 10010001.
uint8_t bcdToDec(uint8_t val) { return ( (val/16*10) + (val%16) ); } uint8_t decToBcd(uint8_t val) { return ( (val/10*16) + (val%10) ); }
Intelligent. Ce serait plus clair cependant s'il serait écrit comme retour (((VAL / 10) << 4) + (Val% 10)); Comme il serait clair que la multiplication de 16 est effectivement laissée à gauche de 4 bits pour déplacer le 1er nybble dans la position la plus significative de l'octet.
#include <stdint.h> /* Standard iterative function to convert 16-bit integer to BCD */ uint32_t dec2bcd(uint16_t dec) { uint32_t result = 0; int shift = 0; while (dec) { result += (dec % 10) << shift; dec = dec / 10; shift += 4; } return result; } /* Recursive one liner because that's fun */ uint32_t dec2bcd_r(uint16_t dec) { return (dec) ? ((dec2bcd_r( dec / 10 ) << 4) + (dec % 10)) : 0; }
J'aime beaucoup ça. Très propre. RX: CHAR * DEC2BCD (CHAR * DEST, UINT16T SRC) Où Déc2TRCD () Copie les NYBbles utilisés en résultat dans DESTS et RETENDS DESTS comme la plupart des fonctions de bibliothèque standard. USHRT_MAX, ne nécessite que 5 nybbles, alias 3 octets. Voici une approche plus rapide, mais j'aime beaucoup les vôtres - aussi loin que cela va. Stackoverflow.com/Questtions/21501815/... < / a>
Ce code code et décode. Les repères sont les suivants.
J'ai utilisé un uint64_t pour stocker le BCD ici. Largeur très pratique et fixe, mais pas très efficace pour les grandes tables. Emballez les chiffres de la BCD, 2 à Char [] pour cela. p> Note: strong>
Il semble que c'est impossible, même avec des INT de 64 bits, de passer à gauche de plus de 32 bits, mais heureusement, il est tout à fait possible de se multiplier par un facteur de 16 - ce qui a heureusement l'effet souhaité. C'est aussi beaucoup plus rapide. Aller figure. P> p>
Je sais que cela a déjà été répondu mais j'ai étendu cela pour les INT non signé de différentes tailles à l'aide d'un modèle pour créer le code spécifique.
#include <stdio.h> #include <unistd.h> #include <stdint.h> #define __STDC_FORMAT_MACROS #include <inttypes.h> constexpr int nBCDPartLength = 4; constexpr int nMaxSleep = 10000; // Wait enough time (in ms) to check out the boundry cases before continuing. // Convert from an integer to a BCD value. // some ideas for this code are from : // http://stackoverflow.com/questions/1408361/unsigned-integer-to-bcd-conversion // && // http://stackoverflow.com/questions/13587502/conversion-from-integer-to-bcd // Compute the last part of the information and place it into the result location. // Decrease the original value to place the next lowest digit into proper position for extraction. template<typename R, typename T> R IntToBCD(T nValue) { int nSizeRtn = sizeof(R); char acResult[nSizeRtn] {}; R nResult { 0 }; int nPos { 0 }; while (nValue) { if (nPos >= nSizeRtn) { return 0; } acResult[nPos] |= nValue % 10; nValue /= 10; acResult[nPos] |= (nValue % 10) << nBCDPartLength; nValue /= 10; ++nPos; } nResult = *(reinterpret_cast<R *>(acResult)); return nResult; } int main(int argc, char **argv) { //uint16_t nValue { 10 }; //printf("The BCD for %d is %x\n", nValue, IntToBCD<uint32_t, uint16_t>(nValue)); // UINT8_MAX = (255) - 2 bytes can be held in uint16_t (2 bytes) // UINT16_MAX = (65535) - 3 bytes can be held in uint32_t (4 bytes) // UINT32_MAX = (4294967295U) - 5 bytes can be held in uint64_t (8 bytes) // UINT64_MAX = (__UINT64_C(18446744073709551615)) - 10 bytes can be held in uint128_t (16 bytes) // Test edge case for uint8 uint8_t n8Value { UINT8_MAX - 1 }; printf("The BCD for %u is %x\n", n8Value, IntToBCD<uint16_t, uint8_t>(n8Value)); // Test edge case for uint16 uint16_t n16Value { UINT16_MAX - 1 }; printf("The BCD for %u is %x\n", n16Value, IntToBCD<uint32_t, uint16_t>(n16Value)); // Test edge case for uint32 uint32_t n32Value { UINT32_MAX - 1 }; printf("The BCD for %u is %" PRIx64 "\n", n32Value, IntToBCD<uint64_t, uint32_t>(n32Value)); // Test edge case for uint64 uint64_t n64Value { UINT64_MAX - 1 }; __uint128_t nLargeValue = IntToBCD<__uint128_t, uint64_t>(n64Value); uint64_t nTopHalf = uint64_t(nLargeValue >> 64); uint64_t nBottomHalf = uint64_t(nLargeValue); printf("The BCD for %" PRIu64 " is %" PRIx64 ":%" PRIx64 "\n", n64Value, nTopHalf, nBottomHalf); usleep(nMaxSleep); // Test all the values for (uint8_t nIdx = 0; nIdx < UINT8_MAX; ++nIdx) { printf("The BCD for %u is %x\n", nIdx, IntToBCD<uint16_t, uint8_t>(nIdx)); } for (uint16_t nIdx = 0; nIdx < UINT16_MAX; ++nIdx) { printf("The BCD for %u is %x\n", nIdx, IntToBCD<uint32_t, uint16_t>(nIdx)); } for (uint32_t nIdx = 0; nIdx < UINT32_MAX; ++nIdx) { printf("The BCD for %u is %" PRIx64 "\n", nIdx, IntToBCD<uint64_t, uint32_t>(nIdx)); } for (uint64_t nIdx = 0; nIdx < UINT64_MAX; ++nIdx) { __uint128_t nLargeValue = IntToBCD<__uint128_t, uint64_t>(nIdx); uint64_t nTopHalf = uint64_t(nLargeValue >> 64); uint64_t nBottomHalf = uint64_t(nLargeValue); printf("The BCD for %" PRIu64 " is %" PRIx64 ":%" PRIx64 "\n", nIdx, nTopHalf, nBottomHalf); } return 0; }
Voici une macro pour uint16_t, de sorte qu'elle soit évaluée au moment de la compilation (à condition que U soit une constante prédéfinie). Cela convient avec déc2T () d'en haut jusqu'à 9999.
#define U16TOBCD(u) ((((u/1000)%10)<<12)|(((u/100)%10)<<8)|\ (((u/10)%10)<<4)|(u%10))
juste simplement simplifié.
#include <math.h> #define uint unsigned int uint Convert(uint value, const uint base1, const uint base2) { uint result = 0; for (int i = 0; value > 0; i++) { result += value % base1 * pow(base2, i); value /= base1; } return result; } uint FromBCD(uint value) { return Convert(value, 16, 10); } uint ToBCD(uint value) { return Convert(value, 10, 16); }
Quel genre de conversion essayez-vous de faire? Le nombre
5 code> est déjà
0101 code> sans avoir besoin de conversion,
7 code> est
0111 code> etc.
Oui. La question a besoin de plus de précision. BCD peut signifier beaucoup de choses. Est-ce un chiffre décimal par octet? Deux chiffres décimaux par octet?
Les processeurs avec support BCD natif (comme la famille M68K) souvent (généralement?) Utilisez deux chiffres décimaux à l'octet.
Vous pouvez avoir emballé BCD, deux chiffres dans un octet: Exemple: 99 -> 10011001b et déballé qui est un chiffre dans un exemple d'octet: 9 -> 00001001b. Lorsque vous souhaitez écrire du code pour cela, gardez ceci dans votre esprit.