2009-07-05 78 views
13

Cho phép nói rằng đầu vào từ người dùng là số thập phân, ví dụ: 5. (có 4 chữ số thập phân). Nó có thể được lưu trữ tự do (int, double), v.v.C/C++ đếm số thập phân?

Có cách nào thông minh (hoặc rất đơn giản) để tìm ra số lượng thập phân mà số có? (kinda giống như câu hỏi làm thế nào để bạn thấy rằng một số là thậm chí hoặc lẻ bằng cách che dấu bit cuối cùng).

+0

Bạn có thể làm rõ "số lượng số thập phân có" không? Bạn có nghĩa là, có bao nhiêu chữ số thập phân trong phần phân số của số? – Doug

+0

Vâng, giả định của bạn là chính xác. – Milan

Trả lời

15

Hai cách tôi biết, không phải rất thông minh không may nhưng điều này là hơn một hạn chế của môi trường chứ không phải là tôi :-)

Đầu tiên là số sprintf số đến một bộ đệm lớn có chuỗi định dạng "%.50f", loại bỏ các số 0 sau đó đếm các ký tự sau dấu thập phân. Điều này sẽ bị giới hạn bởi chính gia đình printf. Hoặc bạn có thể sử dụng chuỗi như đầu vào của người dùng (thay vì sprintf nhập giá trị dấu chấm động), để tránh hoàn toàn các vấn đề về dấu phẩy động.

Thứ hai là trừ phần số nguyên rồi lặp lại nhân với 10 và trừ đi phần số nguyên cho đến khi bạn nhận được 0. Điều này bị giới hạn bởi các giới hạn của biểu diễn máy tính của các số dấu phẩy động - ở mỗi giai đoạn bạn có thể gặp vấn đề về một số không thể được biểu diễn chính xác (vì vậy, 2155 thực sự có thể là .215499999998). Giống như sau (chưa được kiểm tra, ngoại trừ trong đầu tôi, đó là khoảng ngang bằng với một COMx-35):

count = 0 
num = abs(num) 
num = num - int(num) 
while num != 0: 
    num = num * 10 
    count = count + 1 
    num = num - int(num) 

Nếu bạn biết loại số bạn sẽ nhận được (ví dụ như, họ sẽ tất cả được 0 đến 4 chữ số sau dấu thập phân), bạn có thể sử dụng các điểm "thủ thuật" nổi để làm điều đó đúng cách. Ví dụ, thay vì:

while num != 0: 

sử dụng

while abs(num) >= 0.0000001: 
+1

.2155 sẽ không trở thành .21559999999999, nhưng .2156 có thể –

+1

Không ai thích thông minh-alec :-) Cảm ơn, @quant_dev, tôi đã sửa nó. – paxdiablo

+2

Tôi sẽ phân loại là thông minh chỉ vì bạn đã trả lời câu hỏi kỹ lưỡng như thế nào. – ojblass

4

Off đỉnh đầu của tôi:

bắt đầu với phần phân đoạn: .2155

nhiều lần nhân với 10 và vứt bỏ phần nguyên của số cho đến khi bạn có được không. Số lượng các bước sẽ là số thập phân. ví dụ:

.2155 * 10 = 2.155 
.155 * 10 = 1.55 
.55 * 10 = 5.5 
.5 * 10 = 5.0 

4 bước = 4 chữ số thập phân

+0

Điều này cho phép bạn làm tròn các lỗi thực sự dễ dàng. Thử nó. – Bim

2

Ý anh là gì "được lưu trữ một cách tự do (int" Một khi lưu trữ trong một int, nó có zero thập phân còn lại, rõ ràng Một đôi được lưu trữ. Tại sao bạn không giữ đầu vào như một chuỗi, chỉ đủ dài để đếm những số thập phân đó, trước khi gửi nó đến đích cuối cùng biến số của nó?

2

Điều gì đó tương tự cũng có thể hoạt động:

float i = 5.2154; 
std::string s; 
std::string t; 
std::stringstream out; 
out << i; 
s = out.str(); 

t = s.substr(s.find(".")+1); 
cout<<"number of decimal places: " << t.length(); 
+0

Bạn bằng cách nào đó cần phải tính toán số lượng không phù hợp gọn gàng vào một phao, tức là nếu bạn kết thúc với 5.215399999999999, bạn có thể muốn báo cáo 4 chữ số thập phân. –

6

Khi số được chuyển đổi từ biểu diễn người dùng (chuỗi, tệp gif OCR-ed, bất kỳ) thành số dấu phẩy động, bạn không phải xử lý cùng một số. Vì vậy, câu trả lời nghiêm ngặt, không hữu ích là "Không".

Nếu (trường hợp A) bạn có thể tránh chuyển đổi số từ biểu diễn chuỗi, vấn đề trở nên dễ dàng hơn nhiều, bạn chỉ cần đếm các chữ số sau dấu thập phân và trừ số lượng dấu 0.

Nếu bạn không thể làm điều đó (trường hợp B), sau đó bạn cần phải thực hiện một giả định về số lượng tối đa số thập phân, chuyển đổi số trở lại đại diện chuỗi và vòng nó để số lượng tối đa này bằng cách sử dụng round-to-even method. Ví dụ: nếu người dùng cung cấp 1,1 được đại diện là 1.09999999999999 (giả thuyết), hãy chuyển đổi lại thành chuỗi sản lượng, hãy đoán xem "1.09999999999999". Làm tròn số này đến, ví dụ, bốn dấu thập phân cho bạn "1.1000". Bây giờ, nó quay lại trường hợp A.

0

Tôi khuyên bạn nên đọc giá trị dưới dạng chuỗi, tìm kiếm dấu thập phân và phân tích cú pháp văn bản trước và sau văn bản dưới dạng số nguyên. Không có lỗi nổi hoặc làm tròn.

-1

Một cách là đọc số dưới dạng chuỗi. Tìm chiều dài của chuỗi con sau dấu thập phân và đó là số thập phân mà người đó đã nhập. Để chuyển đổi chuỗi này thành một phao bằng cách sử dụng

Trên một lưu ý khác nhau; nó luôn luôn là một ý tưởng tốt khi giao dịch với các hoạt động điểm nổi để lưu trữ chúng trong một đối tượng đặc biệt có độ chính xác hữu hạn. Ví dụ, bạn có thể lưu trữ các điểm phao trong một kiểu đặc biệt của đối tượng được gọi là "Thập phân", trong đó toàn bộ phần số và phần thập phân của số là cả hai ints. Bằng cách này bạn có độ chính xác hữu hạn. Nhược điểm của điều này là bạn phải viết ra các phương thức cho phép toán số học (+, -, *, /, vv), nhưng bạn có thể dễ dàng ghi đè các toán tử trong C++. Tôi biết điều này lệch khỏi câu hỏi ban đầu của bạn, nhưng tốt hơn hết là lưu trữ số thập phân của bạn dưới dạng hữu hạn. Bằng cách này, bạn cũng có thể trả lời câu hỏi của bạn về số lượng thập phân mà số đó có.

+0

Đó là (hầu như) không bao giờ tốt nếu bạn cần tính toán nhanh chóng. –

1

sử dụng định dạng Scientific Notation (để tránh các lỗi làm tròn):

#include <stdio.h> 
#include <string.h> 

/* Counting the number of decimals 
* 
* 1. Use Scientific Notation format 
* 2. Convert it to a string 
* 3. Tokenize it on the exp sign, discard the base part 
* 4. convert the second token back to number 
*/ 

int main(){ 

    int counts; 
    char *sign; 
    char str[15]; 
    char *base; 
    char *exp10; 
    float real = 0.00001; 

    sprintf (str, "%E", real); 
    sign= (strpbrk (str, "+"))? "+" : "-"; 

    base = strtok (str, sign); 
    exp10 = strtok (NULL, sign); 

    counts=atoi(exp10); 

    printf("[%d]\n", counts); 

    return 0; 
} 

[5]

1

năm sau cuộc chiến nhưng như tôi đã thực hiện giải pháp của riêng tôi trong ba dòng:

string number = "543.014";  
size_t dotFound; 
stoi(number, &dotFound)); 
string(number).substr(dotFound).size() 

Tất nhiên bạn phải kiểm tra trước nếu nó thực sự là một phao (Với stof(number) == stoi(number) chẳng hạn)

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