2015-02-04 25 views
5

Tôi mới đến C và khi tôi chạy mã bên dưới, giá trị được đặt ra là 12098 thay vì 12099.Di chuyển vị trí thập phân sang phải trong c

Tôi biết rằng làm việc với số thập phân luôn liên quan đến một mức độ không chính xác, nhưng có cách nào để di chuyển chính xác dấu thập phân đến đúng hai vị trí mỗi lần không?

#include <stdio.h> 

int main(void) 
{ 
    int i; 
    float f = 120.99; 

    i = f * 100; 
    printf("%d", i); 
} 
+0

Hãy thử này 'float i, f = 120.99f;'. – haccks

+0

không có trong tiêu chuẩn C++, bạn cần một loại thập phân, như http://sourceforge.net/projects/stddecimal/ – sp2danny

+0

Sử dụng 'ftoa()' và sao chép từng số vào bộ đệm 'char', bỏ qua ký tự dấu thập phân qua' isdigit() '. –

Trả lời

0

Bạn có thể sử dụng

float f = 120.99f 

hoặc

double f = 120.99 

bởi các giá trị dấu chấm động mặc định c cửa hàng như tăng gấp đôi vì vậy nếu bạn lưu trữ chúng trong phao biến đúc ngầm đang xảy ra và nó là xấu ...
tôi nghĩ rằng nó hoạt động.

+0

không xảy ra khi bạn lưu trữ giá trị 'double' trong biến' float'. Điều gì xảy ra là chuyển đổi tiềm ẩn. –

+0

float là 32 giá trị và gấp đôi là giá trị 64 bit và thuật toán lưu trữ của chúng khác nhau nên việc truyền giữa chúng là nguy hiểm. bạn có thể xem [Wikipeadia] (http://en.wikipedia.org/wiki/Floating_point) để biết chi tiết. –

+0

xin vui lòng không dạy cho tôi số dấu phẩy động. Tôi hoàn toàn nhận thức được những thiếu sót của việc chuyển đổi giữa các số FP có độ chính xác khác nhau. Tôi đã đề cập đến các từ ngữ không chính xác trong câu trả lời của bạn (một "diễn viên" là một chuyển đổi rõ ràng theo định nghĩa; do đó một chuyển đổi tiềm ẩn không thể được gọi là "đúc".) –

5

Sử dụng các chức năng round

float f = 120.99; 
int i = round(f * 100.0); 

Hãy nhận biết tuy nhiên, một float thường chỉ có 6 hoặc 7 chữ số chính xác, vì vậy có một giá trị lớn nhất nơi này sẽ làm việc. Giá trị float nhỏ nhất sẽ không chuyển đổi đúng là số 131072.01. Nếu bạn nhân với 100 và tròn, kết quả sẽ là 13107202.

Bạn có thể mở rộng phạm vi số của mình bằng cách sử dụng các giá trị double, nhưng thậm chí double có phạm vi giới hạn. (A double có 16 hoặc 17 chữ số chính xác.) Ví dụ, đoạn mã sau sẽ in 10000000000000098

double d = 100000000000000.99; 
uint64_t j = round(d * 100.0); 
printf("%llu\n", j); 

Đó chỉ là một ví dụ, tìm số nhỏ nhất là vượt quá độ chính xác của một double là trái như một bài tập cho người đọc.

4

Sử dụng số học điểm cố định trên số nguyên:

#include <stdio.h> 

#define abs(x) ((x)<0 ? -(x) : (x)) 

int main(void) 
{ 
    int d = 12099; 
    int i = d * 100; 
    printf("%d.%02d\n", d/100, abs(d)%100); 
    printf("%d.%02d\n", i/100, abs(i)%100); 
} 
1

Nếu bạn muốn tiếp tục hoạt động trên số như một số dấu chấm động, thì câu trả lời là nhiều hơn hoặc ít không. Có nhiều điều bạn có thể làm cho số nhỏ, nhưng khi số của bạn lớn hơn, bạn sẽ gặp phải sự cố.

Nếu bạn chỉ muốn in số, sau đó đề xuất của tôi sẽ là chuyển đổi số thành chuỗi và sau đó di chuyển dấu thập phân ở đó. Điều này có thể hơi phức tạp tùy thuộc vào cách bạn đại diện cho số trong chuỗi (mũ và những gì không).

Nếu bạn muốn tính năng này hoạt động và bạn không ngại không sử dụng dấu phẩy động, thì tôi khuyên bạn nên nghiên cứu bất kỳ số lượng thư viện thập phân cố định nào.

2

Vấn đề của bạn là phao được thể hiện bằng cách sử dụng IEEE-754. Đó là trong cơ sở 2 và không phải trong cơ sở 10. 0.25 sẽ có một đại diện chính xác, nhưng 0.1 đã không, cũng không có 120.99.

Điều gì thực sự xảy ra là do đến thời điểm inacuracy nổi, IEEE-754 nổi gần nhất với giá trị thập phân 120.99 nhân 100 là hơi thấp hơn 12099, vì vậy nó là cắt ngắn-12098. Trình biên dịch của bạn nên cảnh báo bạn rằng bạn đã cắt ngắn từ phao sang số (tôi đã làm).

Cách duy nhất cao độ để có được những gì bạn mong đợi là thêm 0.5 đến phao trước khi cắt ngắn để int:

i = (f * 100) + 0.5 

Nhưng hãy cẩn thận điểm nổi vốn đã không chính xác khi xử lý các giá trị thập phân.

Edit:

Tất nhiên đối với số âm, nó phải là i = (f * 100) - 0.5 ...

+0

@chux: Đã chỉnh sửa bài đăng. Cảm ơn cho độ chính xác –

+0

Điểm nhỏ: "IEEE-754" không chỉ định cả hai dấu phẩy động và các định dạng thập phân dấu phẩy động mà câu trả lời của bạn dựa vào các nhị phân phổ biến hơn nhiều. Các định dạng thập phân đã phần nào phổ biến trong quá khứ và tôi nghi ngờ rằng chúng sẽ có một sự hồi sinh nhỏ đối với chính xác những loại vấn đề này. – chux

+0

@chux: Tôi đã trích dẫn trang wikipedia cung cấp thêm chi tiết cho lý do đó trong số những người khác. Nhưng nếu hệ thống OP đã sử dụng số thập phân IEEE 754, nó sẽ không tìm thấy bất kỳ vấn đề nào :-) –

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