2010-11-10 73 views
5

về cơ bản tôi muốn trả lại số chữ số trong int -> giá trị như thế này:tìm ra "chuỗi dài" của một int

(int)1 => 1 
(int)123 => 3 
(int)12345678 => 8 

Tôi không biết gì về C, vì vậy hãy chịu với tôi. Tôi biết mục tiêu c, nhưng tôi sử dụng ints và phao thay vì NSNumbers. Tôi nhận ra rằng tôi có thể chuyển đổi ints thành các đối tượng mục tiêu c, nhưng điều này có vẻ là faffy, và nếu tôi có thể làm điều đó với C tôi sẽ biết điều đó cho tương lai.

Cảm ơn

Trả lời

22

sử dụng

int d = (value == 0 ? 1 : (int)(log10(value)+1)); 

Lưu ý rằng việc doesnt này cho số âm, bạn sẽ phải sử dụng

int d = (value == 0 ? 1 : ((int)(log10(fabs(value))+1) + (value < 0 ? 1 : 0))); 

dds 1 cho dấu trừ, nếu value là số âm.

+0

cảm ơn martin. 1 cho tôi số 0 và trừ. :) –

+0

+1 cho cùng một – DVK

+2

(giá trị <0? 1: 0) tương đương với chỉ (giá trị <0) – Vovanium

5

Sử dụng logarit cơ sở 10:

int length = (int)floor(log10((float)number)) + 1; // works for >0 
+0

cảm ơn rất nhiều. :) –

1

Một giải pháp tổng quát hơn, đặc biệt nếu bạn muốn biết chiều dài cho các mục đích in ấn với printf() biến là:

snprintf(NULL, 0, "%d", myint); 

Giá trị trả về sẽ cho bạn biết độ dài của chuỗi đó sẽ được in.

+0

@pst: Tại sao bạn tắt phần '\ 0'? – aib

+0

NUL không được bao gồm trong chuỗi dài chỉ bằng cách là một chuỗi C. (Nó chỉ là cách sử dụng.) –

10

lẽ nhanh hơn nhiều so với sử dụng đăng nhập hoặc chuyển đổi int-to-string và không sử dụng bất kỳ chức năng thư viện là:

int nDigits(int i) 
{ 
    if (i < 0) i = -i; 
    if (i <   10) return 1; 
    if (i <  100) return 2; 
    if (i <  1000) return 3; 
    if (i <  10000) return 4; 
    if (i <  100000) return 5; 
    if (i < 1000000) return 6;  
    if (i < 10000000) return 7; 
    if (i < 100000000) return 8; 
    if (i < 1000000000) return 9; 
    return 10; 
} 

EDIT sau khi Jeff Yates lo ngại:

Đối với những người lo lắng về int kích cỡ khác nhau từ 32-bit (tương tự như giải pháp của PMG nhưng vẫn nhanh hơn vì phép nhân nhanh hơn phân chia :-)

#include <limits.h> 

#define PO10_LIMIT (INT_MAX/10) 


int nDigits(int i) 
{ 
    int n,po10; 

    if (i < 0) i = -i; 
    n=1; 
    po10=10; 
    while(i>=po10) 
    { 
    n++; 
    if (po10 > PO10_LIMIT) break; 
    po10*=10; 
    } 
    return n; 
} 
+1

+1 cho thuật toán nhanh nhất – pmg

+0

Điều này chỉ tốt nếu 'int' là giá trị 32 bit. Vì kích thước của 'int' phụ thuộc vào nền tảng trong C và C++, tôi sẽ không dựa vào điều này. –

+0

@ Jeff Yates: Tôi biết! Nếu điều này, tuy nhiên, thực sự là một vấn đề chỉ cần thêm/loại bỏ một số nếu hướng dẫn. Và nếu bạn thực sự cần một giải pháp hoạt động trên các nền tảng khác nhau, bạn có thể làm việc với thử nghiệm #if cho kích thước của loại int cụ thể hoặc sử dụng giải pháp của pmg (vẫn có thể được tối ưu hóa). – Curd

4

Đây là một lựa chọn

int nDigits(unsigned i) { 
    int n = 1; 
    while (i > 9) { 
     n++; 
     i /= 10; 
    } 
    return n; 
} 

Đây là nhanh hơn so với sử dụng log10, nhưng chậm hơn so với tùy chọn Curd với các bài kiểm tra tầng. Tuy nhiên nó không giả int s là 32 bit :-)

1

Nếu giá trị số nguyên của bạn (ví dụ 12345678u) là một thời gian biên dịch liên tục, bạn có thể cho trình biên dịch xác định độ dài cho bạn:

template<typename T> 
constexpr unsigned int_decimal_digits(T value) 
{ 
    return ( value/10 
        ? int_decimal_digits<T>(value/10) + 1 
        : 1); 
} 

Cách sử dụng:

unsigned n = int_decimal_digits(1234); 
// n = 4 

#include <limits.h> 
unsigned m = int_decimal_digits(ULLONG_MAX); 
// m = maximum length of a "long long unsigned" on your platform 

Bằng cách này, trình biên dịch sẽ tự động tính toán số thập phân và điền giá trị làm hằng số. Nó nên là giải pháp nhanh nhất có thể, bởi vì không có tính toán thời gian chạy liên quan và hằng số nguyên thường được đưa vào các opcodes hướng dẫn. (Điều này có nghĩa là chúng di chuyển bằng đường dẫn lệnh, không phải bởi bộ nhớ/bộ nhớ dữ liệu.) Tuy nhiên, điều này đòi hỏi một trình biên dịch hỗ trợ C++ 11.

Các vấn đề liên quan