web-dev-qa-db-ja.com

ビット単位の演算で整数のN番目の桁を取得するにはどうすればよいですか?

例。 123456、右から3番目( '4')が必要です。

実際のアイデアは、各桁に個別にアクセスすることです(つまり、6 5 4 3 2 1)。

C/C++/C#を推奨。

31
John Smith

より効率的な実装は次のようなものです。

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

これにより、1つの数字だけが必要な場合に、すべての数字を文字列形式に変換する手間が省けます。また、変換された文字列にスペースを割り当てる必要はありません。

速度が問題になる場合は、10の累乗の配列を事前に計算し、nを使用してこの配列にインデックスを付けることができます。

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

他の人が述べたように、これはベース10のビット演算に到達するのと同じくらい近いです。

38
Greg Hewgill

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

生成する:

6
5
4
3
2
1
5
Brannon

ここでの回答に基づいてこれを書くのに時間を費やしただけなので、共有したいと思いました。

これはBrannonの回答に基づいていますが、一度に複数の桁を取得できます。私の場合は、これを使用して、整数がyyyymmddhhnnssm_s形式のintに保存された日時からパーツを抽出します。

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

私はそれを拡張にしたので、あなたはしたくないかもしれませんが、ここにサンプルの使用法があります:

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

結果:

年= 2001

月= 6

日= 7

5
eselk

ビット単位の演算で(簡単に)機能しない理由は、10進法の基数(10)が2進法の基数(2)の累乗ではないためです。

Base 8でコーディングしている場合、pow(2, 3) == 8があり、各8進数を3ビットのブロックとして抽出できます。

したがって、実際には10進数に変換する必要があります。これは通常、文字列に変換することによって行われます(他の人が返信で示したように、toString(Java)またはsprintf(C)を使用)。

3
moritz

説明されているように、これは451069までの符号なし整数に対して機能します here

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.

それをテストする:

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

でも、もっと速いのならびっくりです。多分あなたはあなたの問題を再考する必要があります。

2
Darius Bacon

値=(数値%(10 ^位置))/ 10 ^(位置-1)

例:

数= 23846

位置= 1->値= 6

位置= 2->値= 4

位置= 3->値= 8

これを行う簡単なObjective-Cユーティリティの方法を次に示します:

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

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

楽しみのために、ここに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;
    }
}

使用法:

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

次のコードは、数値の右からn桁目を示します。

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.

これはアセンブラアプローチの可能性があるため、ビット単位の左シフト(N-1の場合)を試し、[0]の桁を読み取ることができます。

123456-> 456->最初の桁を読み取る

0
Karsten