Jak uzyskać pierwszą cyfrę w int (C #)?


82

W C #, jaki jest najlepszy sposób na uzyskanie pierwszej cyfry w int? Metoda, którą wymyśliłem, polega na przekształceniu int w łańcuch, znalezieniu pierwszego znaku ciągu, a następnie przekształceniu go z powrotem w int.

int start = Convert.ToInt32(curr.ToString().Substring(0, 1));

Chociaż to spełnia swoje zadanie, wydaje się, że prawdopodobnie istnieje dobre, proste, matematyczne rozwiązanie takiego problemu. Manipulacja strunami jest niezgrabna.

Edycja: niezależnie od różnic prędkości, mystring [0] zamiast Substring () jest nadal tylko manipulowaniem ciągiem


To jest nawet wolniejsze niż metoda rekurencyjna. =)
J. Steen

mój błąd, zapomniałem zresetować stopera =), jest naprawdę wolniejszy niż inne
Quan Mai

2
To się nie powiedzie na liczbach ujemnych.
cokół

2
pierwsza cyfra liczby int to zawsze 1 z pomijaniem zera (01010101010100101011011011100101) LOL
Zachary Scott

Odpowiedzi:


126

Oto jak

int i = Math.Abs(386792);
while(i >= 10)
    i /= 10;

i ibędzie zawierał to, czego potrzebujesz


222

Benchmarki

Po pierwsze, musisz zdecydować, co rozumiesz przez „najlepsze” rozwiązanie, oczywiście biorąc pod uwagę wydajność algorytmu, jego czytelność / łatwość obsługi oraz prawdopodobieństwo pojawienia się błędów w przyszłości. Jednak dokładne testy jednostkowe pozwalają na ogół uniknąć tych problemów.

Uruchomiłem każdy z tych przykładów 10 milionów razy, a wartość wyniku to liczba ElapsedTicks, które przeszły.

Bez zbędnych ceregieli, algorytmy od najwolniejszego do najszybszego:

Konwertując na łańcuch, weź pierwszy znak

int firstDigit = (int)(Value.ToString()[0]) - 48;

Wyniki:

12,552,893 ticks

Korzystanie z logarytmu

int firstDigit = (int)(Value / Math.Pow(10, (int)Math.Floor(Math.Log10(Value))));

Wyniki:

9,165,089 ticks

Pętla

while (number >= 10)
    number /= 10;

Wyniki:

6,001,570 ticks

Warunki

int firstdigit;
if (Value < 10)
     firstdigit = Value;
else if (Value < 100)
     firstdigit = Value / 10;
else if (Value < 1000)
     firstdigit = Value / 100;
else if (Value < 10000)
     firstdigit = Value / 1000;
else if (Value < 100000)
     firstdigit = Value / 10000;
else if (Value < 1000000)
     firstdigit = Value / 100000;
else if (Value < 10000000)
     firstdigit = Value / 1000000;
else if (Value < 100000000)
     firstdigit = Value / 10000000;
else if (Value < 1000000000)
     firstdigit = Value / 100000000;
else
     firstdigit = Value / 1000000000;

Wyniki:

1,421,659 ticks

Rozwinięta i zoptymalizowana pętla

if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;

Wyniki:

1,399,788 ticks

Uwaga:

każde wywołanie testowe, Random.Next()aby uzyskać następnyint


Sprawdziłem je na jakim zbiorze liczb całkowitych?
mqp

18
To jest baaaaardzo trywialne. Doceniam to, co zrobiłeś i jest to dość pouczające, ale w przypadku 99% aplikacji jest to przesada. Obawiam się, że niektórzy początkujący programiści mogą odnieść złe wrażenie. (twarda, przedwczesna optymalizacja zamiast czytelności) Jednak nadal jest fajnie. :)
Samantha Branham

2
+1 dla testów porównawczych, ale zgadzam się, że to totalna przesada. Jeśli tak bardzo martwisz się o wydajność, prawdopodobnie nie powinieneś używać języka C # w pierwszej kolejności :)
GrahamS

15
+1 - Świetne rzeczy. Jest to rodzaj pozłacanego, luksusowego modelu, który po prostu pokazuje, że kochasz kodowanie. Wielkie uznanie dla ciebie. I nie, Stuart, nie sądzę, żeby to zanieczyściło umysły niczego niepodejrzewających nowicjuszy. Miejmy nadzieję, że nauczy ich to zamiłowania do oprogramowania.
Mark Brittingham

2
@Vikash - rzutowanie a charna an zwraca uwagę intna punkt kodowy znaku, więc rzutowanie znaku 0daje wynik 48. Odejmowanie 48 efektywnie konwertuje na liczbę całkowitą. Jako inny przykład, rzutowanie znaku 5na an daje intw wyniku 53, a odjęcie 48 od tego daje 5.
John Rasch,

31

Spróbuj tego

public int GetFirstDigit(int number) {
  if ( number < 10 ) {
    return number;
  }
  return GetFirstDigit ( (number - (number % 10)) / 10);
}

EDYTOWAĆ

Kilka osób prosiło o wersję pętli

public static int GetFirstDigitLoop(int number)
{
    while (number >= 10)
    {
        number = (number - (number % 10)) / 10;
    }
    return number;
}

1
Rekursja na coś takiego ... Wstydź się. Umieść tam pętlę.
Welbog

@Welbog :), Normalnie bym. Ale mam wiele nostalgii wokół tego konkretnego pytania. To prawie dokładnie pierwsze pytania, jakie kiedykolwiek zadano mi w związku z przydziałem CS. W tamtym czasie pisałem w zasadzie to rozwiązanie.
JaredPar

Tak jest w przypadku, gdy „miło” = wolno
Keltex

Mam nadzieję, że optymalizator zobaczy pierwszą wersję jako coś, co można zoptymalizować pod kątem wywołań ogonowych, w którym to przypadku nie będzie wolniej.
rmeador

1
Ale @Jared, odejmowanie ostatniej cyfry jest tutaj całkowicie niepotrzebne. Po prostu podziel przez 10.
Konrad Rudolph

26

Najlepsze, co mogę wymyślić, to:

int numberOfDigits = Convert.ToInt32(Math.Floor( Math.Log10( value ) ) );

int firstDigit = value / Math.Pow( 10, numberOfDigits );

Możesz uniknąć niepotrzebnych konwersji między liczbami całkowitymi i podwójnymi, używając divisor = Convert.ToInt32 (Math.Pow (10, Math.Floor (Math.Log10 (value)))); firstDigit = wartość / dzielnik;
MartinStettner

Niestety to nie działa, gdy wartość wynosi 1 (zwraca 0) lub jeśli wartość jest ujemna. Poprawka to int numberOfDigits = 1 + Convert.ToInt32 (Math.Floor (Math.Log10 (Math.Abs ​​(wartość))));
DanDan

18

wariacja na temat odpowiedzi Antona:

 // cut down the number of divisions (assuming i is positive & 32 bits)
if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;

Myślę, że zostawiłbym to na /10i /1000. Nadal możesz dzielić bardziej agresywnie, ale z nieco mniejszym bałaganem. +1 za kreatywność :)
Samantha Branham

Przypomina mi funkcję w bcl, którą ktoś odkrył, metoda była dość brzydka do odczytania, ale w zasadzie polegała na wykonywaniu porównań w pętli i łączeniu porównań w grupy po dziesięć, wiedząc, że nowoczesne procesory będą w stanie lepiej obsłużyć grupę porównuje w czasie.
meandmycode

Jest to tylko fantastycznie brzydkie, ponieważ C # nie ma sposobu na wygenerowanie tych stałych w czasie kompilacji (a zrobienie tego w czasie wykonywania byłoby droższe niż to, co próbujesz zapobiec). W języku takim jak Lisp, w którym kontrolujesz czas ewaluacyjny, szybki i elegancki sposób są takie same. :-)
Ken

Rozwinięcie pętli jest z pewnością lepsze niż bzdura instrukcji if / else. Jest jednocześnie elegancki i skuteczny.
Randolpho

3
jeśli zrobisz pierwsze „if” a „while”, będzie działać również z wersją 64-bitową (ale jest jeszcze „brzydsza”). +1
MartinStettner

5
int myNumber = 8383;
char firstDigit = myNumber.ToString()[0];
// char = '8'

Czy to nie jest identyczne z tym, co opublikowałem? Po prostu używa [] zamiast Substring
Dinah

Nie: zwraca znak, a nie ciąg, a wyszukiwanie [] powinno być szybsze
Joel Coehoorn

To prawda, ale nadal jest to ta sama podstawowa metoda - przeanalizuj reprezentację ciągu. Myślę, że @Dinah szuka czegoś ... wiesz ... innego.
Randolpho

@Randolpho: dokładnie. Przepraszam, jeśli nie byłem tego pewien. Zaktualizowałem pytanie, aby wyjaśnić.
Dinah

Zwróciłbym również firstDigit-'0 ', aby uzyskać int. (działa w c ... chyba działa w c #)
Nicolas Irisarri

5

Miał ten sam pomysł co Lennaert

int start = number == 0 ? 0 : number / (int) Math.Pow(10,Math.Floor(Math.Log10(Math.Abs(number))));

Działa to również z liczbami ujemnymi.


4

Jeśli uważasz, że odpowiedź Keltexa jest brzydka, wypróbuj tę, jest NAPRAWDĘ brzydka, a nawet szybsza. W celu określenia długości wykonuje rozwinięte wyszukiwanie binarne.

 ... leading code along the same lines
/* i<10000 */
if (i >= 100){
  if (i >= 1000){
    return i/1000;
  }
  else /* i<1000 */{
    return i/100;
  }
}
else /* i<100*/ {
  if (i >= 10){
    return i/10;
  }
  else /* i<10 */{
    return i;
  }
}

PS MartinStettner wpadł na ten sam pomysł.


@Rasch: Ach, zachwyt! Powinien być ukryty, wyjmowany tylko na specjalne okazje i czytany przyciszonym tonem ... Kto powiedział, że programowanie nie ma duszy?
Mike Dunlavey

co powiesz nai=(...moreugly...)i>=100?i>=1000?i/1000:i/100:i>=10?i/10:i;
David Murdoch,

3

Oczywistym, ale powolnym podejściem matematycznym jest:

int firstDigit = (int)(i / Math.Pow(10, (int)Math.Log10(i))));

Czas, to wcale nie powinno być powolne. To miała być moja sugestia, a biorąc pod uwagę, że jest to rozwiązanie czysto matematyczne bez pętli, prawdopodobnie jest szybsze niż wiele rozwiązań tutaj. Należy pamiętać, że każdy sprzedawany obecnie procesor x86 ma bardzo, bardzo szybki i zdolny procesor zmiennoprzecinkowy.
Adam Davis

Myślę, że naprawdę powinien używać Math.Log10 tutaj
MartinStettner

Dzięki, Martin - nie używam zbyt często bibliotek matematycznych .NET i zapomniałem, że to Log i Log10 zamiast Log i Ln.
mqp

Cóż, Adamie, przynajmniej musi mieć 10 ^ (N-1) (n to liczba cyfr) plus logarytm. W porównaniu z zapętloną odpowiedzią (gdzie dzielisz N - 1 razy) wydaje mi się, że musi być przynajmniej trochę wolniejsza. Ale regularnie jestem zaskoczony benchmarkami, więc kto wie.
mqp

1
Poza tym w PO zażądano bardziej znaczącego wyrażenia, bez względu na wyniki, i jest to najbardziej bezpośredni (matematyczny) sposób wyrażenia tego, czego się poszukuje.
harpo

3
int temp = i;
while (temp >= 10)
{
    temp /= 10;
}

Skutkować w temp


@ck: Jakie wydano zaokrąglenie? Dzielenie jest w tym przypadku dzieleniem całkowitoliczbowym, każdy podział dokładnie odcina ostatnią cyfrę ...
MartinStettner

3

Wiem, że to nie jest C #, ale zaskakujące jest to, że w Pythonie "pobierz pierwszy znak ciągu reprezentującego liczbę" jest szybsze!

EDYCJA : nie, popełniłem błąd, zapomniałem ponownie skonstruować int, przepraszam. Wersja rozwinięta jest najszybsza.

$ cat first_digit.py
def loop(n):
    while n >= 10:
        n /= 10
    return n

def unrolled(n):
    while n >= 100000000: # yea... unlimited size int supported :)
        n /= 100000000
    if n >= 10000:
        n /= 10000
    if n >= 100:
        n /= 100
    if n >= 10:
        n /= 10
    return n

def string(n):
    return int(str(n)[0])
$ python -mtimeit -s 'from first_digit import loop as test' \
    'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 275 msec per loop
$ python -mtimeit -s 'from first_digit import unrolled as test' \
    'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 149 msec per loop
$ python -mtimeit -s 'from first_digit import string as test' \
    'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 284 msec per loop
$

Ale czy zamienia go z powrotem na liczbę całkowitą?
Samuel

woops, teraz to ma sens -.-
ZeD

cóż, mógł powiedzieć, że to IronPython sprawił, że ten nieco mniej nie na temat
Ravi,

3

Właśnie natknąłem się na to stare pytanie i czułem się skłonny zaproponować inną sugestię, ponieważ żadna z dotychczasowych odpowiedzi nie zwraca poprawnego wyniku dla wszystkich możliwych wartości wejściowych i nadal można to zrobić szybciej:

public static int GetFirstDigit( int i )
{
    if( i < 0 && ( i = -i ) < 0 ) return 2;
    return ( i < 100 ) ? ( i < 1 ) ? 0 : ( i < 10 )
            ? i : i / 10 : ( i < 1000000 ) ? ( i < 10000 )
            ? ( i < 1000 ) ? i / 100 : i / 1000 : ( i < 100000 )
            ? i / 10000 : i / 100000 : ( i < 100000000 )
            ? ( i < 10000000 ) ? i / 1000000 : i / 10000000
            : ( i < 1000000000 ) ? i / 100000000 : i / 1000000000;
}

Działa to dla wszystkich wartości całkowitych ze -2147483648znakiem włącznie, która jest najmniejszą liczbą całkowitą ze znakiem i nie ma dodatniego odpowiednika. Math.Abs( -2147483648 )wyzwala a System.OverflowExceptioni - -2147483648oblicza do-2147483648 .

Wdrożenie można postrzegać jako połączenie zalet dwóch dotychczas najszybszych wdrożeń. Używa wyszukiwania binarnego i unika zbędnych podziałów. Szybki test porównawczy z indeksem pętli z 100 000 000 iteracjami pokazuje, że jest on dwa razy szybszy niż obecnie najszybsza implementacja.

Kończy się po 2829581 tyknięciach.

Dla porównania zmierzyłem również poprawiony wariant najszybszej obecnie implementacji, która zajęła 5664627 ticków .

public static int GetFirstDigitX( int i )
{
    if( i < 0 && ( i = -i ) < 0 ) return 2;
    if( i >= 100000000 ) i /= 100000000;
    if( i >= 10000 ) i /= 10000;
    if( i >= 100 ) i /= 100;
    if( i >= 10 ) i /= 10;
    return i;
}

Przyjęta odpowiedź z tą samą poprawką wymagała 16 561 929 taktów do tego testu na moim komputerze.

public static int GetFirstDigitY( int i )
{
    if( i < 0 && ( i = -i ) < 0 ) return 2;
    while( i >= 10 )
        i /= 10;
    return i;
}

Proste funkcje, takie jak te, można łatwo udowodnić pod względem poprawności, ponieważ iteracja wszystkich możliwych wartości całkowitych zajmuje niewiele więcej niż kilka sekund na obecnym sprzęcie. Oznacza to, że wdrażanie ich w wyjątkowo czytelny sposób jest mniej ważne, ponieważ po prostu nigdy nie będzie potrzeby naprawiania błędu w nich później.


2

Bardzo proste (i prawdopodobnie dość szybkie, ponieważ obejmuje tylko porównania i jeden podział):

if(i<10)
   firstdigit = i;
else if (i<100)
   firstdigit = i/10;
else if (i<1000)
   firstdigit = i/100;
else if (i<10000)
   firstdigit = i/1000;
else if (i<100000)
   firstdigit = i/10000;
else (etc... all the way up to 1000000000)

1
A potem jest 10k, 100k, 1mil, 10mil, 100mil i tak dalej?
Paweł Krakowiak

Zrobiłbym to w ten sposób. O wiele bardziej wydajna niż ta rekurencyjna funkcja.
Keltex

Ta odpowiedź jest najlepsza ze wszystkich.
Brian

Wydajność kupiona kosztem naprawdę, naprawdę brzydkiego, powtarzalnego, niemożliwego do utrzymania kodu. Co by było, gdybyś przypadkowo pominął stopień? Ups.
Randolpho

Naprawdę powinieneś zmienić kolejność tych warunków, aby najbardziej prawdopodobne były na górze ...
Jason Punyon

1

Przeprowadziłem tutaj kilka testów z jednym z moich współpracowników i odkryłem, że większość rozwiązań nie działa dla liczb poniżej 0.

  public int GetFirstDigit(int number)
    {
        number = Math.Abs(number); <- makes sure you really get the digit!

        if (number < 10)
        {
            return number;
        }
        return GetFirstDigit((number - (number % 10)) / 10);
    }

1

Korzystając ze wszystkich poniższych przykładów, aby uzyskać ten kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Benfords
{
    class Program
    {
        static int FirstDigit1(int value)
        {
            return Convert.ToInt32(value.ToString().Substring(0, 1));
        }

        static int FirstDigit2(int value)
        {
            while (value >= 10) value /= 10;
            return value;
        }


        static int FirstDigit3(int value)
        {
            return (int)(value.ToString()[0]) - 48;
        }

        static int FirstDigit4(int value)
        {
            return (int)(value / Math.Pow(10, (int)Math.Floor(Math.Log10(value))));
        }

        static int FirstDigit5(int value)
        {
            if (value < 10) return value;
            if (value < 100) return value / 10;
            if (value < 1000) return value / 100;
            if (value < 10000) return value / 1000;
            if (value < 100000) return value / 10000;
            if (value < 1000000) return value / 100000;
            if (value < 10000000) return value / 1000000;
            if (value < 100000000) return value / 10000000;
            if (value < 1000000000) return value / 100000000;
            return value / 1000000000;
        }

        static int FirstDigit6(int value)
        {
            if (value >= 100000000) value /= 100000000;
            if (value >= 10000) value /= 10000;
            if (value >= 100) value /= 100;
            if (value >= 10) value /= 10;
            return value;
        }

        const int mcTests = 1000000;

        static void Main(string[] args)
        {
            Stopwatch lswWatch = new Stopwatch();
            Random lrRandom = new Random();

            int liCounter;

            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit1(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 1, lswWatch.ElapsedTicks);

            lswWatch.Reset();
            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit2(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 2, lswWatch.ElapsedTicks);

            lswWatch.Reset();
            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit3(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 3, lswWatch.ElapsedTicks);

            lswWatch.Reset();
            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit4(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 4, lswWatch.ElapsedTicks);

            lswWatch.Reset();
            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit5(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 5, lswWatch.ElapsedTicks);

            lswWatch.Reset();
            lswWatch.Start();
            for (liCounter = 0; liCounter < mcTests; liCounter++)
                FirstDigit6(lrRandom.Next());
            lswWatch.Stop();
            Console.WriteLine("Test {0} = {1} ticks", 6, lswWatch.ElapsedTicks);

            Console.ReadLine();
        }
    }
}

Otrzymuję te wyniki na dwurdzeniowym AMD Ahtlon 64 X2 4200+ (2,2 GHz):

Test 1 = 2352048 ticks
Test 2 = 614550 ticks
Test 3 = 1354784 ticks
Test 4 = 844519 ticks
Test 5 = 150021 ticks
Test 6 = 192303 ticks

Ale zdobądź je na ośmiordzeniowym AMD FX 8350 (4,00 GHz)

Test 1 = 3917354 ticks
Test 2 = 811727 ticks
Test 3 = 2187388 ticks
Test 4 = 1790292 ticks
Test 5 = 241150 ticks
Test 6 = 227738 ticks

Więc to, czy metoda 5 lub 6 jest szybsza, zależy od procesora, mogę tylko przypuszczać, że to dlatego, że przewidywanie gałęzi w procesorze poleceń procesora jest inteligentniejsze w nowym procesorze, ale nie jestem do końca pewien.

Nie mam żadnych procesorów Intela, może ktoś mógłby to dla nas przetestować?


1

Sprawdź też to:

int get1digit(Int64 myVal)
{
    string q12 = myVal.ToString()[0].ToString();
    int i = int.Parse(q12);
    return i;
}

Również dobrze, jeśli chcesz mieć wiele liczb:

int get3digit(Int64 myVal) //Int64 or whatever numerical data you have
{
    char mg1 = myVal.ToString()[0];
    char mg2 = myVal.ToString()[1];
    char mg3 = myVal.ToString()[2];
    char[] chars = { mg1, mg2, mg3 };
    string q12= new string(chars);
    int i = int.Parse(q12);
    return i;
}

Czy mógłbyś dodać wyjaśnienie do swojej odpowiedzi? To pytanie ma już 24 inne odpowiedzi - dobrze byłoby wiedzieć, dlaczego powinniśmy używać twojego, a nie innych.
Wai Ha Lee

W oryginalnym rozwiązaniu mam kilka błędów przy użyciu dużych liczb. Moje rozwiązanie jest czystsze. Nie ma za co.
teodoric8.

Twoje rozwiązanie zawodzi -1.
Wai Ha Lee

:) użyj tego wtedy: if (myVal.ToString () [0]! = '-') {....} i - znak nie jest liczbą!
teodoric8.

Dlaczego nie sprawdzić, czy liczba nie jest ujemna, zamiast sprawdzać ciąg?
Wai Ha Lee

0
while (i > 10)
{
   i = (Int32)Math.Floor((Decimal)i / 10);
}
// i is now the first int

Dlaczego przechodzisz na dziesiętny? Również podłoga nie jest potrzebna.
MartinStettner

Było tam dla potencjalnych problemów z zaokrąglaniem, które w rzeczywistości nie są potrzebne.
cjk

Powinno być while (i> = 10), bo inaczej zakończy się niepowodzeniem dla wielokrotności 10.
Bill the Lizard

0

Formuła nie iteracyjna:

public static int GetHighestDigit(int num)
{
    if (num <= 0)
       return 0; 

    return (int)((double)num / Math.Pow(10f, Math.Floor(Math.Log10(num))));
}

Implementacja Log jest iteracyjna, ponieważ wymaga algorytmu znajdowania korzeni
Jasper Bekkers

0

Aby dać ci alternatywę, możesz wielokrotnie podzielić liczbę całkowitą przez 10, a następnie cofnąć o jedną wartość po osiągnięciu zera. Ponieważ operacje na łańcuchach są generalnie powolne, może to być szybsze niż manipulacja na łańcuchach, ale w żadnym wypadku nie jest eleganckie.

Coś takiego:

while(curr>=10)
     curr /= 10;

Dokonać while-warunek (Curr> 10) i nie trzeba prevValue
MartinStettner

> = jest potrzebne. Pierwsza cyfra 10 powinna być 1, a nie 10
Dinah

0
start = getFirstDigit(start);   
public int getFirstDigit(final int start){
    int number = Math.abs(start);
    while(number > 10){
        number /= 10;
    }
    return number;
}

lub

public int getFirstDigit(final int start){
  return getFirstDigit(Math.abs(start), true);
}
private int getFirstDigit(final int start, final boolean recurse){
  if(start < 10){
    return start;
  }
  return getFirstDigit(start / 10, recurse);
}

Powinien teraz działać. Dodano również funkcję rekurencyjną z pułapką na abs.
sdellysse

0
int start = curr;
while (start >= 10)
  start /= 10;

Jest to bardziej wydajne niż podejście ToString (), które wewnętrznie musi implementować podobną pętlę i musi po drodze skonstruować (i przeanalizować) obiekt ciągu ...


0

Bardzo łatwa metoda uzyskania ostatniej cyfry:

int myInt = 1821;

int lastDigit = myInt - ((myInt/10)*10); // 1821 - 1820 = 1

3
To miłe, ale pytanie brzmi: uzyskać pierwszą cyfrę, a nie ostatnią.
Dinah

0

To jest to, co zwykle robię, proszę odnieść się do mojej funkcji poniżej:

Ta funkcja może wyodrębnić pierwsze wystąpienie liczby z dowolnego ciągu, który możesz zmodyfikować, i użyć tej funkcji zgodnie ze swoim użyciem

   public static int GetFirstNumber(this string strInsput)
    {
        int number = 0;
        string strNumber = "";
        bool bIsContNo = true;
        bool bNoOccued = false;

        try
        {
            var arry = strInsput.ToCharArray(0, strInsput.Length - 1);

            foreach (char item in arry)
            {
                if (char.IsNumber(item))
                {
                    strNumber = strNumber + item.ToString();

                    bIsContNo = true;

                    bNoOccued = true;
                }
                else
                {
                    bIsContNo = false;
                }

                if (bNoOccued && !bIsContNo)
                {
                    break;
                }


            }

            number = Convert.ToInt32(strNumber);

        }
        catch (Exception ex)
        {

            return 0;
        }

        return number;

    }

-2

Oto prostszy sposób, który nie wymaga zapętlenia

int number = 1234
int firstDigit = Math.Floor(number/(Math.Pow(10, number.ToString().length - 1))

To dałoby nam 1234 / Math.Pow (10, 4 - 1) = 1234/1000 = 1


Nie można niejawnie przekonwertować typu „double” na „int”.
Younes

-2
int i = 4567789;
int digit1 = int.Parse(i.ToString()[0].ToString());
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.