it-swarm.com.de

Wie erhalte ich die n-te Ziffer einer Ganzzahl mit bitweisen Operationen?

Beispiel. 123456, und wir wollen den dritten von rechts ('4') raus.

In der Praxis besteht die Idee darin, auf jede Ziffer einzeln zuzugreifen (z. B. 6 5 4 3 2 1).

C/C++/C # bevorzugt.

31
John Smith

Eine effizientere Implementierung könnte etwa so aussehen:

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

Dies erspart den Aufwand, alle Ziffern in ein String-Format umzuwandeln, wenn Sie nur eine davon wünschen. Und Sie müssen keinen Platz für die konvertierte Zeichenfolge zuweisen.

Wenn Geschwindigkeit ein Problem ist, können Sie ein Array von Potenzen von 10 vorberechnen und n verwenden, um in dieses Array zu indexieren:

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

Wie bereits von anderen erwähnt, ist dies so nah wie Sie bitweise Operationen für die Basis 10 erhalten.

38
Greg Hewgill

Ich habe einfach Zeit damit verbracht, dies auf der Grundlage der Antworten zu schreiben, also dachte ich, ich würde es teilen.

Dies basiert auf Brannons Antwort, aber Sie können mehr als eine Ziffer gleichzeitig erhalten. In meinem Fall verwende ich es, um Teile aus einem Datum und einer Zeit zu extrahieren, die in einem int gespeichert wurden, wobei die Ziffern im Format jjjjmmmmthhnnssm_s vorliegen.

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

Ich habe es eine Erweiterung gemacht, die Sie vielleicht nicht möchten, aber hier ist ein Beispiel für die Verwendung:

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

ergebnisse:

jahr = 2001

monat = 6

tag = 7

5
eselk

Verwenden Sie Basis-10-Mathematik:

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;
    }
}

Produziert:

6
5
4
3
2
1
4
Brannon

Der Grund dafür, dass es mit bitweisen Operationen (leicht) nicht funktioniert, ist, dass die Basis des Dezimalsystems (10) keine Potenz der Basis des Binärsystems (2) ist.

Wenn Sie in Basis 8 programmieren würden, hätten Sie pow(2, 3) == 8 und könnten jede Oktalziffer als Block von drei Bits extrahieren.

Sie müssen also wirklich in Basis 10 konvertieren, was normalerweise durch Konvertierung in einen String (mit toString (Java) oder sprintf (C), wie die anderen Antworten gezeigt haben) erfolgt.

3
moritz

Dies funktioniert für unsignierte Ints bis zu 451069, wie erklärt hier :

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.

Testen Sie es aus:

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

Ich wäre allerdings überrascht, wenn es schneller geht. Vielleicht sollten Sie Ihr Problem noch einmal überdenken.

2
Darius Bacon

Wert = (Anzahl% (10 ^ Position))/10 ^ (Position - 1)

Beispiel:

zahl = 23846

position = 1 -> Wert = 6

position = 2 -> Wert = 4

position = 3 -> Wert = 8

Hier ist eine einfache Objective-C-Utility-Methode, um dies zu tun:

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

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

Nur zum Spaß ist hier die C # -Erweiterungsklasse dafür:

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;
    }
}

Verwendungszweck:

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

Der folgende Code gibt die n-te Stelle von rechts in einer Zahl ein:

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.

Sie könnten eine bitweise Verschiebung nach links (für N-1) versuchen und dann die Ziffer bei [0] lesen, da dies ein Assembler-Ansatz sein könnte.

123456 -> 456 -> Erste Ziffer lesen

0
Karsten