Wie können Sie die erste Ziffer in einem int (C #) erhalten?

81

Was ist in C # der beste Weg, um die erste Ziffer in einem Int zu erhalten? Die Methode, die ich mir ausgedacht habe, besteht darin, das int in einen String umzuwandeln, das erste Zeichen des Strings zu finden und es dann wieder in einen int umzuwandeln.

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

Während dies die Arbeit erledigt, scheint es wahrscheinlich eine gute, einfache, mathematische Lösung für ein solches Problem zu geben. Die Manipulation von Saiten fühlt sich klobig an.

Bearbeiten: Unabhängig von Geschwindigkeitsunterschieden ist mystring [0] anstelle von Substring () immer noch nur eine String-Manipulation

Dinah
quelle
Das ist sogar langsamer als die rekursive Methode. =)
J. Steen
Mein schlechtes, ich habe vergessen, die Stoppuhr zurückzusetzen =), es ist wirklich langsamer als andere
Quan Mai
2
Dies schlägt bei negativen Zahlen fehl.
Sockel
2
Die erste Ziffer eines int ist immer 1 mit Nullunterdrückung (01010101010100101011011011100101) LOL
Zachary Scott

Antworten:

126

Hier ist wie

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

und iwird enthalten, was Sie brauchen

Anton Gogolev
quelle
221

Benchmarks

Zunächst müssen Sie entscheiden, was Sie unter "bester" Lösung verstehen. Dabei werden natürlich die Effizienz des Algorithmus, seine Lesbarkeit / Wartbarkeit und die Wahrscheinlichkeit berücksichtigt, dass in Zukunft Fehler auftreten. Sorgfältige Komponententests können diese Probleme jedoch im Allgemeinen vermeiden.

Ich habe jedes dieser Beispiele 10 Millionen Mal ausgeführt, und der Ergebniswert ist die Anzahl der ElapsedTicksübergebenen Beispiele.

Ohne weiteres, vom langsamsten zum schnellsten, sind die Algorithmen:

Nehmen Sie zum Konvertieren in eine Zeichenfolge das erste Zeichen

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

Ergebnisse:

12,552,893 ticks

Verwenden eines Logarithmus

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

Ergebnisse:

9,165,089 ticks

Schleifen

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

Ergebnisse:

6,001,570 ticks

Bedingungen

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;

Ergebnisse:

1,421,659 ticks

Abgerollte und optimierte Schleife

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

Ergebnisse:

1,399,788 ticks

Hinweis:

Jeder Test ruft Random.Next()an, um den nächsten zu erhaltenint

John Rasch
quelle
17
Das ist soooooo trivial. Ich weiß zu schätzen, was Sie getan haben, und es ist ziemlich informativ, aber für 99% der Anwendungen ist es so übertrieben. Ich befürchte, einige unerfahrene Programmierer könnten einen schlechten Eindruck bekommen. (Hardcore, vorzeitige Optimierungen über Lesbarkeit) Es macht trotzdem Spaß. :)
Samantha Branham
7
Wo ist die Nachschlagetabelle?
GvS
2
+1 für Benchmarks, aber ich stimme zu, dass dies ein totaler Overkill ist. Wenn Sie sich Sorgen um die Leistung machen, sollten Sie C # wahrscheinlich gar nicht erst verwenden :)
GrahamS
14
+1 - Tolles Zeug. Dies ist die Art von vergoldetem Overkill mit Deluxe-Modell, die nur deutlich macht, dass Sie das Codieren lieben. Ein großes Lob an Sie. Und nein, Stuart, ich glaube nicht, dass dies den Geist ahnungsloser Neulinge verschmutzen wird. Hoffentlich wird es ihnen beibringen, eine Liebe zur Software zu entwickeln.
Mark Brittingham
2
@Vikash - Das Umwandeln von a charin a ergibt intden Codepunkt des Zeichens. Wenn Sie also das Zeichen 0in 48 umwandeln, wird durch Subtrahieren von 48 effektiv eine Konvertierung in eine Ganzzahl durchgeführt. Als weiteres Beispiel ergibt das Wirken des Charakters 5auf eine intBewertung von 53 und das Subtrahieren von 48 davon 5.
John Rasch
31

Versuche dies

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

BEARBEITEN

Mehrere Personen haben die Loop-Version angefordert

public static int GetFirstDigitLoop(int number)
{
    while (number >= 10)
    {
        number = (number - (number % 10)) / 10;
    }
    return number;
}
JaredPar
quelle
1
Rekursion für so etwas ... Schande über dich. Legen Sie dort eine Schleife ein.
Welbog
@ Welbog :), normalerweise würde ich. Aber ich habe viel Nostalgie um diese spezielle Frage. Es waren fast genau die ersten Fragen, die mir jemals für eine CS-Aufgabe gestellt wurden. Zu der Zeit habe ich im Wesentlichen diese Lösung geschrieben.
JaredPar
Dies ist der Fall, wo "schön" = langsam
Keltex
Ich würde hoffen, dass der Optimierer die erste Version als etwas sieht, das für Tail-Call-Optimierungen optimiert werden kann. In diesem Fall wäre sie nicht langsamer.
Rmeador
1
Aber, @Jared, die Subtraktion der letzten Ziffer ist hier völlig unnötig. Teilen Sie einfach durch 10.
Konrad Rudolph
26

Das Beste, was ich mir einfallen lassen kann, ist:

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

int firstDigit = value / Math.Pow( 10, numberOfDigits );
Lennaert
quelle
Sie können unnötige Konvertierungen zwischen Ganzzahlen und Doppelwerten vermeiden, indem Sie divisor = Convert.ToInt32 (Math.Pow (10, Math.Floor (Math.Log10 (Wert))) verwenden. firstDigit = Wert / Divisor;
MartinStettner
Leider funktioniert dies nicht, wenn der Wert 1 ist (0 zurückgibt) oder wenn der Wert negativ ist. Der Fix lautet int numberOfDigits = 1 + Convert.ToInt32 (Math.Floor (Math.Log10 (Math.Abs ​​(Wert)));
DanDan
18

Variation von Antons Antwort:

 // 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;
Mike Dunlavey
quelle
Ich denke, ich würde es einfach bei /10und lassen /1000. Sie haben immer noch den Vorteil, aggressiver zu teilen, aber mit etwas weniger Chaos. +1 für Kreativität :)
Samantha Branham
Erinnert mich an eine Funktion in bcl, die jemand entdeckt hat. Die Methode war ziemlich hässlich zu lesen, aber sie führte im Grunde genommen Schleifenvergleiche durch und ordnete Vergleiche in Zehnergruppen oder so, in dem Wissen, dass moderne CPUs in der Lage sein würden, eine Gruppe von besser zu handhaben vergleicht zu einem Zeitpunkt.
Meandmycode
Es ist nur fantastisch hässlich, weil C # keine Möglichkeit hat, diese Konstanten zur Kompilierungszeit zu generieren (und dies zur Laufzeit zu tun, wäre teurer als das, was Sie verhindern möchten). In einer Sprache wie Lisp, in der Sie die Auswertungszeit steuern, sind der schnelle und der elegante Weg gleich. :-)
Ken
Das Abrollen einer Schleife ist sicherlich besser als eine Menge if / else-Anweisungen. Es ist sowohl elegant als auch performant.
Randolpho
3
Wenn Sie das erste "if" a "while" machen, funktioniert es auch mit 64-Bit (ist aber noch "hässlicher"). +1
MartinStettner
5

Hatte die gleiche Idee wie Lennaert

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

Dies funktioniert auch mit negativen Zahlen.

Aquin
quelle
4
int myNumber = 8383;
char firstDigit = myNumber.ToString()[0];
// char = '8'
jgauffin
quelle
Ist das nicht identisch mit dem, was ich gepostet habe? Es verwendet nur [] anstelle von Teilzeichenfolge
Dinah
Nein: Es wird eher ein Zeichen als eine Zeichenfolge zurückgegeben, und die [] Suche sollte schneller sein
Joel Coehoorn,
Das stimmt, aber es ist immer noch dieselbe grundlegende Methode - analysieren Sie die Zeichenfolgendarstellung. Ich denke, @Dinah sucht etwas ... weißt du ... anders.
Randolpho
@ Randolpho: genau. Entschuldigung, wenn mir das nicht klar war. Ich habe die Frage aktualisiert, um sie zu klären.
Dinah
Ich würde auch firstDigit-'0 'zurückgeben, um das int zu erhalten. (es funktioniert in c ... ich denke, es funktioniert in c #)
Nicolas Irisarri
4

Wenn Sie der Meinung sind, dass Keltex 'Antwort hässlich ist, probieren Sie diese aus, sie ist WIRKLICH hässlich und sogar noch schneller. Es führt eine entrollte binäre Suche durch, um die Länge zu bestimmen.

 ... 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 hatte die gleiche Idee.

Mike Dunlavey
quelle
@ Rasch: Ah, die Entrückung! Es sollte versteckt, nur zu besonderen Anlässen herausgebracht und in gedämpften Tönen gelesen werden ... Wer sagt, dass Programmieren keine Seele hat?
Mike Dunlavey
wie wäre esi=(...moreugly...)i>=100?i>=1000?i/1000:i/100:i>=10?i/10:i;
David Murdoch
3

Ein offensichtlicher, aber langsamer mathematischer Ansatz ist:

int firstDigit = (int)(i / Math.Pow(10, (int)Math.Log10(i))));
mqp
quelle
Mal es, es sollte überhaupt nicht langsam sein. Dies war mein Vorschlag, und da es sich um eine rein mathematische Lösung ohne Schleifen handelt, ist sie möglicherweise schneller als viele Lösungen hier. Beachten Sie, dass jeder heute verkaufte x86-Prozessor über einen sehr, sehr schnellen und leistungsfähigen Gleitkomma-Prozessor verfügt.
Adam Davis
Ich denke, Sie sollten Math.Log10 wirklich hier verwenden
MartinStettner
Danke, Martin - ich benutze nicht viel .NET-Mathematikbibliotheken und habe vergessen, dass es Log und Log10 anstelle von Log und Ln war.
mqp
Nun, Adam, zumindest muss es 10 ^ (N-1) (n ist die Anzahl der Ziffern) und einen Logarithmus benötigen. Im Vergleich zu einer Schleifenantwort (bei der Sie N - 1 mal teilen) scheint es mir, dass sie mindestens etwas langsamer sein muss. Aber ich bin regelmäßig von Benchmarks überrascht, also wer weiß.
mqp
1
Außerdem forderte das OP einen aussagekräftigeren Ausdruck, unabhängig von der Leistung, und dies ist der direkteste (mathematische) Weg, um auszudrücken, was gesucht wird.
Harpo
3
int temp = i;
while (temp >= 10)
{
    temp /= 10;
}

Ergebnis in temp

Douglas Leeder
quelle
@ck: Welche Rundung ausgegeben? Division ist in diesem Fall Integer-Division, jede Division schneidet genau die letzte Ziffer ab ...
MartinStettner
3

Ich weiß, dass es nicht C # ist, aber es ist überraschend merkwürdig, dass in Python das "Erhalten des ersten Zeichens der Zeichenfolgendarstellung der Zahl" schneller ist!

EDIT : Nein, ich habe einen Fehler gemacht, ich habe vergessen, das Int erneut zu konstruieren, sorry. Die abgerollte Version ist die schnellste.

$ 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
$
ZeD
quelle
Aber konvertiert es es zurück in eine ganze Zahl?
Samuel
woops, jetzt macht es Sinn -.-
ZeD
Nun, er konnte sagen, dass es IronPython war, um dieses etwas weniger themenunabhängig zu machen
Ravi
3

Ich bin gerade auf diese alte Frage gestoßen und war geneigt, einen anderen Vorschlag vorzuschlagen, da keine der anderen Antworten bisher das richtige Ergebnis für alle möglichen Eingabewerte liefert und es immer noch schneller gemacht werden kann:

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

Dies funktioniert für alle vorzeichenbehafteten Ganzzahlwerte einschließlich, wobei -2147483648dies die kleinste vorzeichenbehaftete Ganzzahl ist und kein positives Gegenstück hat. Math.Abs( -2147483648 )löst a aus System.OverflowExceptionund - -2147483648berechnet zu-2147483648 .

Die Implementierung kann als eine Kombination der Vorteile der beiden bisher schnellsten Implementierungen angesehen werden. Es verwendet eine binäre Suche und vermeidet überflüssige Unterteilungen. Ein schneller Benchmark mit dem Index einer Schleife mit 100.000.000 Iterationen zeigt, dass sie doppelt so schnell ist wie die derzeit schnellste Implementierung.

Es endet nach 2.829.581 Zecken.

Zum Vergleich habe ich auch eine korrigierte Variante der derzeit schnellsten Implementierung gemessen, die 5.664.627 Ticks benötigte.

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

Die akzeptierte Antwort mit der gleichen Korrektur benötigte 16.561.929 Ticks für diesen Test auf meinem Computer.

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

Einfache Funktionen wie diese können leicht auf ihre Richtigkeit überprüft werden, da das Iterieren aller möglichen ganzzahligen Werte auf der aktuellen Hardware nicht viel länger als einige Sekunden dauert. Dies bedeutet, dass es weniger wichtig ist, sie auf außergewöhnlich lesbare Weise zu implementieren, da es später einfach nie notwendig sein wird, einen Fehler in ihnen zu beheben.

x4u
quelle
2

Sehr einfach (und wahrscheinlich ziemlich schnell, da es sich nur um Vergleiche und eine Unterteilung handelt):

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)
Keltex
quelle
Und dann gibt es 10k, 100k, 1mil, 10mil, 100mil und so weiter?
Pawel Krakowiak
Ich würde es so machen. Viel effizienter als diese rekursive Funktion.
Keltex
Diese Antwort ist die beste des ganzen Haufen.
Brian
Effizienz, die auf Kosten von wirklich, wirklich, wirklich hässlichem, sich wiederholendem, nicht wartbarem Code gekauft wurde. Was wäre, wenn Sie versehentlich einen Rang übersprungen hätten? Hoppla.
Randolpho
Sie sollten diese Bedingungen wirklich neu ordnen, damit die wahrscheinlichsten oben sind ...
Jason Punyon
1

Ich habe einige Tests mit einem meiner Mitarbeiter hier durchgeführt und festgestellt, dass die meisten Lösungen für Zahlen unter 0 nicht funktionieren.

  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);
    }
Younes
quelle
1

Verwenden Sie alle folgenden Beispiele, um diesen Code zu erhalten:

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

Ich erhalte diese Ergebnisse auf einem AMD Ahtlon 64 X2 Dual Core 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

Aber erhalten Sie diese auf einem AMD FX 8350 Eight Core (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

Ob Methode 5 oder 6 schneller ist oder nicht, hängt von der CPU ab. Ich kann nur vermuten, dass die Verzweigungsvorhersage im Befehlsprozessor der CPU auf dem neuen Prozessor intelligenter ist, aber ich bin mir nicht sicher.

Ich habe keine Intel-CPUs, vielleicht könnte es jemand für uns testen?

Aaron Murgatroyd
quelle
1

Überprüfen Sie auch dieses:

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

Auch gut, wenn Sie mehrere Zahlen möchten:

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;
}
teodoric8.
quelle
Könnten Sie Ihrer Antwort eine Erklärung hinzufügen? Diese Frage hat bereits 24 andere Antworten - es wäre gut zu wissen, warum wir Ihre anstelle der anderen verwenden sollten.
Wai Ha Lee
Mit der ursprünglichen Lösung habe ich einige Fehler mit großen Zahlen bekommen. Meine Lösung ist sauberer. Bitte.
teodoric8.
Ihre Lösung schlägt fehl für -1.
Wai Ha Lee
:) benutze dies dann: if (myVal.ToString () [0]! = '-') {....} und - Zeichen ist keine Zahl!
teodoric8.
Warum nicht überprüfen, ob die Zahl nicht negativ ist, anstatt die Zeichenfolge zu überprüfen?
Wai Ha Lee
0
while (i > 10)
{
   i = (Int32)Math.Floor((Decimal)i / 10);
}
// i is now the first int
cjk
quelle
Warum konvertieren Sie in Dezimal? Auch Boden wird nicht benötigt.
MartinStettner
Es war für potenzielle Rundungsprobleme da, die eigentlich nicht benötigt werden.
cjk
Sollte während (i> = 10) sein oder dies wird für ein Vielfaches von 10 fehlschlagen.
Bill the Lizard
0

Nicht iterative Formel:

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

    return (int)((double)num / Math.Pow(10f, Math.Floor(Math.Log10(num))));
}
Mitch Wheat
quelle
Die Implementierung von Log ist iterativ, da ein Root-Finding-Algorithmus erforderlich ist
Jasper Bekkers
0

Um Ihnen eine Alternative zu bieten, können Sie die Ganzzahl wiederholt durch 10 teilen und dann einen Wert zurücksetzen, sobald Sie Null erreichen. Da String-Operationen im Allgemeinen langsam sind, ist dies möglicherweise schneller als die String-Manipulation, aber keineswegs elegant.

Etwas wie das:

while(curr>=10)
     curr /= 10;
JoshJordan
quelle
Machen Sie die while-Bedingung (curr> 10) und Sie brauchen keinen prevValue
MartinStettner
> = wird benötigt. Die erste Ziffer von 10 sollte 1 sein, nicht 10
Dinah
0
start = getFirstDigit(start);   
public int getFirstDigit(final int start){
    int number = Math.abs(start);
    while(number > 10){
        number /= 10;
    }
    return number;
}

oder

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);
}
sdellysse
quelle
Sollte jetzt funktionieren. Außerdem wurde eine rekursive Funktion mit Trap für abs hinzugefügt.
sdellysse
0
int start = curr;
while (start >= 10)
  start /= 10;

Dies ist effizienter als ein ToString () -Ansatz, der intern eine ähnliche Schleife implementieren muss und unterwegs ein String-Objekt erstellen (und analysieren) muss ...

MartinStettner
quelle
0

Sehr einfache Methode, um die letzte Ziffer zu erhalten:

int myInt = 1821;

int lastDigit = myInt - ((myInt/10)*10); // 1821 - 1820 = 1
Daniel
quelle
3
Das ist schön, aber die Frage ist, die erste Ziffer zu bekommen, nicht die letzte.
Dinah
0

Dies ist, was ich normalerweise mache, bitte beziehen Sie sich auf meine Funktion unten:

Diese Funktion kann das Auftreten der ersten Nummer aus jeder Zeichenfolge extrahieren, die Sie ändern und entsprechend Ihrer Verwendung verwenden können

   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;

    }
Sreeyushs
quelle
-2

Hier ist ein einfacher Weg, der keine Schleife beinhaltet

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

Das würde uns 1234 / Math.Pow (10, 4 - 1) = 1234/1000 = 1 geben

Ross Goddard
quelle
Typ 'double' kann nicht implizit in 'int' konvertiert werden.
Younes
-2
int i = 4567789;
int digit1 = int.Parse(i.ToString()[0].ToString());
jrod
quelle