web-dev-qa-db-fra.com

Comment obtenir le Nième chiffre d'un entier avec des opérations en bits?

Exemple. 123456, et nous voulons que le troisième de la droite ('4') soit sorti.

En pratique, l’idée est d’accéder séparément à chaque chiffre (par exemple, 6 5 4 3 2 1).

C/C++/C # préféré.

31
John Smith

Une implémentation plus efficace pourrait ressembler à ceci:

char nthdigit(int x, int n)
{
    while (n--) {
        x /= 10;
    }
    return (x % 10) + '0';
}

Cela vous évite de convertir tous les chiffres au format chaîne si vous ne souhaitez que l'un d'entre eux. Et vous ne devez pas allouer d'espace pour la chaîne convertie.

Si la vitesse est une préoccupation, vous pouvez précalculer un tableau de puissances de 10 et utiliser n pour indexer dans ce tableau:

char nthdigit(int x, int n)
{
    static int powersof10[] = {1, 10, 100, 1000, ...};
    return ((x / powersof10[n]) % 10) + '0';
}

Comme mentionné par d’autres, c’est aussi proche que vous allez arriver aux opérations au niveau des bits pour la base 10.

38
Greg Hewgill

Je viens de passer du temps à écrire ceci en fonction des réponses ici, alors je pensais partager.

Ceci est basé sur la réponse de Brannon, mais vous permet d’obtenir plus d’un chiffre à la fois. Dans mon cas, je l'utilise pour extraire des parties d'une date et d'une heure enregistrées dans un entier dont les chiffres sont au format aaaammjjdhhnnssm_s.

public static int GetDigits(this int number, int highestDigit, int numDigits)
{
    return (number / (int)Math.Pow(10, highestDigit - numDigits)) % (int)Math.Pow(10, numDigits);
}

J'en ai fait une extension, vous ne voudrez peut-être pas, mais voici un exemple d'utilisation:

int i = 20010607;
string year = i.GetDigits(8,4).ToString();
string month = i.GetDigits(4,2).ToString();
string day = i.GetDigits(2,2).ToString();

résultats:

année = 2001

mois = 6

jour = 7

5
eselk

Utilisez les mathématiques en base 10:

class Program
{
    static void Main(string[] args)
    {
        int x = 123456;

        for (int i = 1; i <= 6; i++)
        {
            Console.WriteLine(GetDigit(x, i));
        }
    }

    static int GetDigit(int number, int digit)
    {
        return (number / (int)Math.Pow(10, digit - 1)) % 10;
    }
}

Produit:

6
5
4
3
2
1
4
Brannon

La raison pour laquelle cela ne fonctionnera pas (facilement) avec les opérations binaires est que la base du système décimal (10) n'est pas une puissance de la base du système binaire (2).

Si vous codiez en base 8, vous auriez pow(2, 3) == 8 et pourrez extraire chaque chiffre octal sous forme de bloc de trois bits.

Il faut donc vraiment convertir en base 10, ce qui se fait généralement en convertissant une chaîne (avec toString (Java) ou sprintf (C), comme les autres l’ont montré dans leurs réponses).

3
moritz

Cela fonctionne pour les fichiers non signés jusqu'à 451069, comme expliqué ici :

def hundreds_digit(u): return mod10(div100(u))

def div100(u): return div10(div10(u))
def mod10(u):  return u - mul10(div10(u))
def mul10(u):  return ((u << 2) + u) << 1

def div10(u):
    Q = ((u >> 1) + u) >> 1  # Q = u*0.11
    Q = ((Q >> 4) + Q)       # Q = u*0.110011
    Q = ((Q >> 8) + Q) >> 3  # Q = u*0.00011001100110011
    return Q

# Alternatively:
#   def div100(u): return (u * 0xa3d7) >> 22
# though that'd only work for 16-bit u values.
# Or you could construct shifts and adds along the lines of div10(),
# but I didn't go to the trouble.

Le tester:

>>> hundreds_digit(123456)
4
>>> hundreds_digit(123956)
9

Je serais surpris si c'est plus rapide, cependant. Peut-être devriez-vous reconsidérer votre problème.

2
Darius Bacon

valeur = (nombre% (10 ^ position))/10 ^ (position - 1)

Exemple:

nombre = 23846

position = 1 -> valeur = 6

position = 2 -> valeur = 4

position = 3 -> valeur = 8

Voici une méthode d'utilitaire Objective-C simple pour ce faire:

+ (int)digitAtPosition:(int)pos of:(int)number {

    return (number % ((int)pow(10, pos))) / (int)pow(10, pos - 1);
}
1
Michael Peterson

Juste pour le plaisir, voici la classe d’extension C #:

public static class IntExtensions
{
    /// <summary>
    /// Returns the nth digit from an int, 
    /// where 0 is the least significant digit 
    /// and n is the most significant digit.
    /// </summary>
    public static int GetDigit(this int number, int digit)
    {
        for (int i = 0; i < digit; i++)
        {
            number /= 10;
        }
        return number % 10;
    }
}

Usage:

int myNumber = 12345;
int five = myNumber.GetDigit(0);
int four = myNumber.GetDigit(1);
int three = myNumber.GetDigit(2);
int two = myNumber.GetDigit(3);
int one = myNumber.GetDigit(4);
int zero = myNumber.GetDigit(5);
0
Evorlor

Le code suivant donnera le nième chiffre à partir de la droite dans un nombre:

public void getDigit(long n,int k){
    int i=0;
    long r =0;
    while(i<n){
        r=n%10;
        n=n/10;
        i++;
    }
    System.out.println( k + "th digit from right " + r);
 }
0
Sonal S.

Vous pouvez essayer un décalage binaire à gauche (pour N-1), puis lire le chiffre en [0], car il pourrait s'agir d'une approche assembleur.

123456 -> 456 -> lire le premier chiffre

0
Karsten