Làm thế nào bạn có thể lấy chữ số đầu tiên trong một int (C #)?


82

Trong C #, cách tốt nhất để lấy chữ số đầu tiên trong một int là gì? Phương pháp tôi nghĩ ra là biến int thành một chuỗi, tìm ký tự thứ nhất của chuỗi, sau đó biến nó trở lại thành int.

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

Trong khi điều này thực hiện công việc, có vẻ như có lẽ có một giải pháp tốt, đơn giản, dựa trên toán học cho một vấn đề như vậy. Thao tác chuỗi cảm thấy lộn xộn.

Chỉnh sửa: bất kể sự khác biệt về tốc độ, mystring [0] thay vì Substring () vẫn chỉ là thao tác chuỗi


Điều đó thậm chí còn chậm hơn so với phương pháp đệ quy. =)
— J. Steen

xấu của tôi, tôi quên để thiết lập lại đồng hồ bấm giờ =), nó thực sự chậm hơn so với những người khác
— Quan Mai

2
Điều này sẽ không thành công trên số âm.
— plinth

2
các chữ số đầu tiên của một int luôn 1 là với zero ức chế (01010101010100101011011011100101) LOL
— Zachary Scott

Câu trả lời:


126

Đây là cách

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

và isẽ chứa những gì bạn cần


222

Điểm chuẩn

Đầu tiên, bạn phải quyết định xem giải pháp "tốt nhất" có nghĩa là gì, tất nhiên có tính đến hiệu quả của thuật toán, khả năng đọc / bảo trì của nó và khả năng xuất hiện lỗi trong tương lai. Tuy nhiên, các bài kiểm tra đơn vị cẩn thận thường có thể tránh được những vấn đề đó.

Tôi đã chạy mỗi ví dụ này 10 triệu lần và giá trị kết quả là số trong số ElapsedTicksđó đã qua.

Không cần thêm lời khuyên, từ chậm nhất đến nhanh nhất, các thuật toán là:

Chuyển đổi thành một chuỗi, lấy ký tự đầu tiên

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

Các kết quả:

12,552,893 ticks

Sử dụng một lôgarit

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

Các kết quả:

9,165,089 ticks

Vòng lặp

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

Các kết quả:

6,001,570 ticks

Điều kiện

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;

Các kết quả:

1,421,659 ticks

Vòng lặp chưa được cuộn và tối ưu hóa

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

Các kết quả:

1,399,788 ticks

Ghi chú:

mỗi cuộc gọi kiểm tra Random.Next()để có đượcint


18
Điều này là quá tầm thường. Tôi đánh giá cao những gì bạn đã làm và nó khá nhiều thông tin, nhưng nó quá mức cần thiết đối với 99% ứng dụng. Tôi e rằng một số lập trình viên mới vào nghề có thể có ấn tượng xấu. (lõi cứng, tối ưu hóa quá sớm so với khả năng đọc) Tuy nhiên, nó vẫn rất thú vị. :)
— Samantha Branham

7
Bảng tra cứu ở đâu?
— GvS

2
+1 cho điểm chuẩn, nhưng tôi đồng ý rằng đây là tổng số quá mức cần thiết. Nếu bạn đang lo lắng về hiệu suất RẰNG thì có thể bạn không nên sử dụng C # ở nơi đầu tiên :)
— GrahamS

15
+1 - Nội dung tuyệt vời. Đây là loại mạ vàng, kiểu mẫu sang trọng quá mức cần thiết để khiến bạn thấy rõ rằng bạn yêu thích mã hóa. Nhiều kudo cho bạn. Và không, Stuart, tôi không nghĩ điều này sẽ làm ô nhiễm tâm trí của những người mới không nghi ngờ. Hy vọng rằng nó sẽ dạy họ phát triển niềm yêu thích phần mềm.
— Mark Brittingham

2
@Vikash - ép kiểu charthành một intđánh giá đến điểm mã của ký tự, do đó, việc ép kiểu ký tự được 0đánh giá là 48. Phép trừ 48 thực hiện chuyển đổi thành số nguyên một cách hiệu quả. Một ví dụ khác, đúc nhân vật 5đến một intđánh giá lại đến 53, và trừ 48 từ kết quả mà trong 5.
— John Rasch

31

Thử đi

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

BIÊN TẬP

Một số người đã yêu cầu phiên bản vòng lặp

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

1
Đệ quy cho một cái gì đó như thế này ... Xấu hổ cho bạn. Đặt một vòng lặp vào đó.
— Welbog

@Welbog :), Tôi thường làm vậy. Nhưng tôi có rất nhiều hoài niệm xung quanh câu hỏi cụ thể này. Đó gần như chính xác là những câu hỏi đầu tiên mà tôi từng được hỏi cho một nhiệm vụ CS. Vào thời điểm đó tôi đã viết về cơ bản giải pháp này.
— JaredPar

Đây là trường hợp "nice" = slow
— Keltex

Tôi hy vọng trình tối ưu hóa sẽ xem phiên bản đầu tiên là một thứ có thể được tối ưu hóa theo yêu cầu, trong trường hợp đó, nó sẽ không chậm hơn.
— rmeador

1
Nhưng, @Jared, phép trừ chữ số cuối cùng là hoàn toàn không cần thiết ở đây. Chỉ cần chia cho 10.
— Konrad Rudolph

26

Điều tốt nhất tôi có thể nghĩ ra là:

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

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

Bạn có thể tránh các chuyển đổi không cần thiết giữa số nguyên và số nhân đôi bằng cách sử dụng divisor = Convert.ToInt32 (Math.Pow (10, Math.Floor (Math.Log10 (value)))); firstDigit = giá trị / số chia;
— MartinStettner

Thật không may, điều này không hoạt động khi giá trị là 1 (trả về 0) hoặc nếu giá trị là âm. Bản sửa lỗi là int numberOfDigits = 1 + Convert.ToInt32 (Math.Floor (Math.Log10 (Math.Abs ​​(value))));
— DanDan,

18

biến thể về câu trả lời của Anton:

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

Tôi nghĩ rằng tôi sẽ chỉ để nó ở /10và /1000. Bạn vẫn có được lợi thế khi phân chia một cách quyết liệt hơn, nhưng ít lộn xộn hơn một chút. +1 cho sự sáng tạo :)
— Samantha Branham

Nhắc tôi về một hàm trong bcl mà ai đó đã phát hiện ra, phương pháp này khá xấu để đọc, nhưng về cơ bản nó thực hiện so sánh vòng lặp và đang nhóm các so sánh thành nhóm mười hoặc hơn, biết rằng cpu hiện đại sẽ có thể xử lý tốt hơn một nhóm so sánh tại một thời điểm.
— mã của bạn vào

Nó chỉ cực kỳ xấu vì C # không có cách nào để tạo ra những khuyết điểm đó trong thời gian biên dịch (và làm điều đó trong thời gian chạy sẽ tốn kém hơn những gì bạn đang cố gắng ngăn chặn). Trong một ngôn ngữ như Lisp, nơi bạn kiểm soát thời gian, cách nhanh và cách thanh lịch là như nhau. :-)
— Ken

Việc hủy một vòng lặp chắc chắn tốt hơn một đống câu lệnh if / else. Nó vừa thanh lịch vừa biểu diễn.
— Randolpho

3
nếu bạn tạo "if" a "while" đầu tiên, nó cũng hoạt động với 64-bit (nhưng thậm chí còn "xấu hơn"). +1
— MartinStettner

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

Điều này không giống với những gì tôi đã đăng? Nó chỉ sử dụng [] thay vì Chuỗi con
— Dinah

Số: nó trả về một nhân vật chứ không phải là một chuỗi và [] tra cứu cần được nhanh hơn
— Joel Coehoorn

Điều đó đúng, nhưng nó vẫn là phương thức cơ bản giống nhau - phân tích cú pháp biểu diễn chuỗi. Tôi nghĩ @Dinah đang tìm kiếm thứ gì đó ... bạn biết đấy .... khác biệt.
— Randolpho

@Randolpho: chính xác. Xin lỗi nếu tôi không rõ về điều đó. Tôi đã cập nhật câu hỏi để làm rõ.
— Dinah,

Tôi cũng sẽ trả về firstDigit-'0 'để lấy int. (nó hoạt động trong c ... tôi đoán nó trong c #)
— Nicolas Irisarri

5

Có cùng ý tưởng với Lennaert

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

Điều này cũng hoạt động với số âm.


4

Nếu bạn nghĩ câu trả lời của Keltex là xấu, hãy thử câu này, nó THỰC SỰ xấu và thậm chí còn nhanh hơn. Nó thực hiện tìm kiếm nhị phân không được cuộn để xác định độ dài.

 ... 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 cũng có ý tưởng tương tự.


@Rasch: Ah, sự sung sướng! Nó chỉ nên được giấu đi, chỉ mang ra cho những dịp đặc biệt, và đọc bằng giọng nói kín đáo ... Ai nói rằng lập trình không có linh hồn?
— Mike Dunlavey

thế còni=(...moreugly...)i>=100?i>=1000?i/1000:i/100:i>=10?i/10:i;
— David Murdoch

3

Một cách tiếp cận toán học hiển nhiên, nhưng chậm chạp là:

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

Thời gian đi, không nên chậm chút nào. Đây sẽ là gợi ý của tôi, và cho rằng đó là một giải pháp thuần túy toán học không có vòng lặp, nó có thể nhanh hơn nhiều giải pháp ở đây. Hãy nhớ rằng mọi bộ xử lý x86 được bán ngày nay đều có một bộ xử lý dấu chấm động rất, rất nhanh và có khả năng.
— Adam Davis,

Tôi nghĩ rằng bạn thực sự cần sử dụng Math.Log10 đây
— MartinStettner

Cảm ơn, Martin - Tôi không sử dụng nhiều thư viện toán học .NET và quên rằng nó là Log và Log10 thay vì Log và Ln.
— mqp

À, Adam, ít nhất nó cần lấy 10 ^ (N-1) (n là số chữ số) cộng với nó cần lấy một logarit. So với một câu trả lời lặp lại (trong đó bạn đang chia N - 1 lần) thì với tôi, dường như nó phải chậm hơn một chút. Nhưng tôi thường xuyên bị ngạc nhiên bởi các điểm chuẩn, vì vậy ai mà biết được.
— mqp

1
Bên cạnh đó, OP yêu cầu một biểu thức có ý nghĩa hơn, không liên quan đến hiệu suất, và đây là cách trực tiếp nhất (toán học) để diễn đạt những gì đang được tìm kiếm.
— harpo

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

Kết quả là temp


@ck: phát hành vòng tròn nào? Division là số nguyên phân chia trong trường hợp này, mỗi bộ phận chính xác sẽ cắt đứt chữ số cuối cùng ...
— MartinStettner

3

Tôi biết đó không phải là C #, nhưng thật đáng ngạc nhiên là trong python, "lấy ký tự đầu tiên của biểu diễn chuỗi của số" nhanh hơn!

CHỈNH SỬA : không, tôi đã mắc lỗi, tôi đã quên xây dựng lại int, xin lỗi. Phiên bản chưa được cuộn là nhanh nhất.

$ 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
$

Nhưng nó có chuyển đổi nó trở lại một số nguyên không?
— Samuel,

woops, bây giờ nó có ý nghĩa -.-
— ZeD

tốt anh có thể nói rằng đó là IronPython để làm điều này hơi ít off-topic
— Ravi

3

Tôi chỉ tình cờ gặp câu hỏi cũ này và cảm thấy có xu hướng đề xuất một đề xuất khác vì không có câu trả lời nào khác trả lại kết quả chính xác cho tất cả các giá trị đầu vào có thể có và nó vẫn có thể được thực hiện nhanh hơn:

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

Điều này hoạt động cho tất cả các giá trị số nguyên có dấu, bao gồm cả giá trị số nguyên -2147483648có dấu nhỏ nhất và không có đối số dương. Math.Abs( -2147483648 )kích hoạt a System.OverflowExceptionvà - -2147483648tính đến -2147483648.

Việc triển khai có thể được coi là sự kết hợp những ưu điểm của hai cách triển khai nhanh nhất cho đến nay. Nó sử dụng một tìm kiếm nhị phân và tránh các phân chia thừa. Một điểm chuẩn nhanh với chỉ số của một vòng lặp với 100.000.000 lần lặp cho thấy rằng nó nhanh gấp đôi so với việc triển khai nhanh nhất hiện tại.

Nó kết thúc sau 2.829.581 tích tắc.

Để so sánh, tôi cũng đã đo lường một biến thể đã được hiệu chỉnh của việc triển khai nhanh nhất hiện nay, mất 5.664.627 tick.

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

Câu trả lời được chấp nhận với cùng một hiệu chỉnh cần 16.561.929 tích tắc cho bài kiểm tra này trên máy tính của tôi.

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

Các hàm đơn giản như thế này có thể dễ dàng được chứng minh về tính đúng đắn vì việc lặp lại tất cả các giá trị số nguyên có thể mất không quá vài giây trên phần cứng hiện tại. Điều này có nghĩa là việc triển khai chúng theo cách đặc biệt dễ đọc sẽ ít quan trọng hơn vì đơn giản là sau này sẽ không cần phải sửa một lỗi bên trong chúng.


2

Rất đơn giản (và có lẽ khá nhanh vì nó chỉ liên quan đến phép so sánh và một phép chia):

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
Và sau đó là 10k, 100k, 1 triệu, 10 triệu, 100 triệu, v.v.?
— Pawel Krakowiak,

Tôi sẽ làm theo cách này. Hiệu quả hơn rất nhiều so với hàm đệ quy đó.
— Keltex,

Câu trả lời này là tốt nhất trong số các câu trả lời.
— Brian,

Hiệu quả được mua bằng cái giá phải trả là mã thực sự thực sự xấu, lặp đi lặp lại, không thể xác định được. Điều gì sẽ xảy ra nếu bạn vô tình bỏ qua một thứ hạng? Rất tiếc.
— Randolpho

Bạn thực sự nên sắp xếp lại các điều kiện đó sao cho khả năng cao nhất ở trên cùng ...
— Jason Punyon

1

Đã thực hiện một số thử nghiệm với một trong những đồng nghiệp của tôi ở đây và phát hiện ra hầu hết các giải pháp không hoạt động cho các số dưới 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

Sử dụng tất cả các ví dụ bên dưới để lấy mã này:

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

Tôi nhận được những kết quả này trên 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

Nhưng hãy tải những thứ này trên AMD FX 8350 lõi tám (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

Vì vậy, phương pháp 5 hay 6 nhanh hơn hay không phụ thuộc vào CPU, tôi chỉ có thể phỏng đoán điều này là do dự đoán nhánh trong bộ xử lý lệnh của CPU thông minh hơn trên bộ xử lý mới, nhưng tôi không thực sự chắc chắn.

Tôi không có bất kỳ CPU Intel nào, có thể ai đó có thể kiểm tra nó cho chúng tôi?


1

Kiểm tra cái này quá:

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

Cũng tốt nếu bạn muốn nhiều số:

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

Bạn có thể thêm một số giải thích cho câu trả lời của bạn? Câu hỏi này đã có 24 câu trả lời khác - sẽ rất tốt nếu biết tại sao chúng ta nên sử dụng câu trả lời của bạn hơn là những câu khác.
— Wai Ha Lee

Với giải pháp ban đầu, tôi gặp một số lỗi khi sử dụng số lượng lớn. Giải pháp của tôi sạch hơn. Không có gì.
— teodoric8.

Giải pháp của bạn không thành công cho -1.
— Wai Ha Lee

:) sử dụng điều này sau đó: if (myVal.ToString () [0]! = '-') {....} và dấu - không phải là một số!
— teodoric8.

Tại sao không kiểm tra số không âm thay vì kiểm tra chuỗi?
— Wai Ha Lee

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

Tại sao bạn chuyển đổi sang Hệ thập phân? Ngoài ra Tầng không cần thiết.
— MartinStettner

Nó ở đó cho các vấn đề làm tròn tiềm năng, điều này thực sự không cần thiết.
— cjk

Nên khi (i> = 10) hoặc này sẽ thất bại cho bội số của 10.
— Bill the Lizard

0

Công thức không lặp lại:

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

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

Thực hiện Log là lặp đi lặp lại vì nó đòi hỏi phải có một thuật toán gốc tìm hiểu
— Jasper Bekkers

0

Chỉ để cung cấp cho bạn một giải pháp thay thế, bạn có thể chia nhiều lần số nguyên cho 10 và sau đó khôi phục một giá trị khi bạn đạt đến số không. Vì các thao tác trên chuỗi thường chậm, điều này có thể nhanh hơn thao tác với chuỗi, nhưng không có nghĩa là thanh lịch.

Một cái gì đó như thế này:

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

Tạo điều kiện trong khi (curr> 10) và bạn không cần giá trị trước
— MartinStettner

> = là cần thiết. Chữ số đầu tiên của 10 phải là 1, không phải 10
— Dinah

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

hoặc là

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

Nên làm việc ngay bây giờ. Cũng được thêm chức năng đệ quy với bẫy cho abs.
— sdellysse

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

Cách này hiệu quả hơn cách tiếp cận ToString () mà bên trong phải triển khai một vòng lặp tương tự và phải xây dựng (và phân tích cú pháp) một đối tượng chuỗi trên đường ...


0

Phương pháp rất dễ dàng để lấy chữ số cuối cùng:

int myInt = 1821;

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

3
Điều đó thật tuyệt, nhưng câu hỏi đặt ra là lấy chữ số Đầu tiên, không phải chữ số Cuối cùng.
— Dinah

0

Đây là những gì tôi thường làm, vui lòng tham khảo chức năng của tôi bên dưới:

Hàm này có thể trích xuất lần xuất hiện số đầu tiên từ bất kỳ chuỗi nào bạn có thể sửa đổi và sử dụng hàm này theo cách sử dụng của bạn

   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

Đây là một cách đơn giản hơn không liên quan đến vòng lặp

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

Điều đó sẽ cho chúng ta 1234 / Math.Pow (10, 4 - 1) = 1234/1000 = 1


Không thể chuyển đổi hoàn toàn kiểu 'double' thành 'int'.
— Younes

-2
int i = 4567789;
int digit1 = int.Parse(i.ToString()[0].ToString());
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.