2012-03-19 57 views
10

này cư xử như muốn:Tại sao (1/2) * x khác với 0,5 * x?

double t = r[1][0] * .5; 

Nhưng điều này không:

double t = ((1/2)*r[1][0]); 

r là một 2-D Vector.

Chỉ cần nghĩ đến khả năng. Có phải vì (1/2) được coi là int(1/2) == 0?

+55

Tại sao một vấn đề cơ bản về các số nguyên so với các loại float được bỏ phiếu? – tbert

+29

Không chỉ cơ bản, nhưng OP đã có câu trả lời nhưng không thử. Bình chọn rất ngẫu nhiên trong SO ... –

+4

Nó nhận được thêm nhãn cầu vì nó là một "câu hỏi nóng" trong StackExchange. Thêm nhãn cầu = phiếu bầu bổ sung. –

Trả lời

58

Có phải vì (1/2) được coi là int và (1/2) == 0 không?

Vâng, cả những chữ thuộc loại int, do đó kết quả sẽ là loại int, và kết quả là 0.

Thay vào đó, thực hiện một trong những literals một float hoặc double và bạn' sẽ kết thúc với kết quả điểm nổi của 0.5, ví dụ:

double t = ((1.0/2)*r[1][0]);

1.0 là loại double, số int 2 sẽ được thăng cấp thành double và kết quả sẽ là double.

14

Viết này thay vì:

double t = ((1/2.0)*r[1][0]); 

1/2 là một bộ phận nguyên và kết quả là 0.

1/2.0 là bộ phận dấu chấm động (với giá trị double sau chuyển đổi số học thông thường) và kết quả là 0.5.

5

1/2int/int chia. Điều đó có nghĩa là bất cứ điều gì là kết quả sẽ có bất cứ điều gì sau khi dấu thập phân được loại bỏ (cắt ngắn). Vì vậy 1/2 = 0,5 = 0.

Bình thường, tôi luôn viết số đầu tiên trong double: 1.0/2 ... ..

Nếu bạn làm cho số đầu tiên một double sau đó tất cả các tính còn lại được thực hiện trong chỉ double.

+0

Không nhất thiết phải * số đầu tiên *, chỉ một trong số ít nhất. – Marlon

+0

Chỉ cần thực hiện thói quen sử dụng số đầu tiên là phao thì bạn sẽ không gặp phải bất ngờ. Một thói quen tốt khác là bắt đầu với 1.0 * .... – AgA

+2

Lưu ý rằng trong '2.0 * x + (7/5)', số đầu tiên là 'double' và vấn đề của OP vẫn tồn tại. –

2
double t = r[1][0] * .5; 

tương đương với:

double t = ((1/2f)*r[1][0]); 

và không:

double t = ((1/2)*r[1][0]); 

Do mất một phần thập phân khi kết quả tạm thời của 1/2 được lưu trữ trong một biến int.

Như một hướng dẫn bất cứ khi nào có một sự chia rẽ và có một khả năng của câu trả lời là số thực, không sử dụng int hay làm cho một trong những toán hạng float hoặc double hoặc sử dụng đúc.

1

Thay vào đó, bạn có thể viết 1.0/2.0. 1/2 hiển thị hành vi này bởi vì cả mẫu số và hành vi tử số là một kiểu số nguyên và một biến của một kiểu số nguyên chia cho một biến khác của một kiểu số nguyên luôn bị cắt ngắn thành một số nguyên.

0

Tôi không thể đánh giá hoặc loại bỏ tiêu chuẩn của câu hỏi nhưng vấn đề này dường như rất quan trọng đối với tôi. Chúng tôi giả định rằng trình biên dịch sẽ giặt quần áo cho chúng ta mọi lúc, nhưng that is not true một số lần.

Có cách nào để tránh tình trạng này không?

Possibly

HOẶC

Quan trọng hơn biết con quái vật (C, C++) như hầu hết những người chỉ ra ở trên

Tôi muốn biết nếu có những cách khác để theo dõi những " cắt ngắn "các vấn đề tại thời điểm biên dịch

+0

Làm cách nào để biết ngôn ngữ và kiểm tra mã của bạn? –

+0

@JonathonReinhart không tranh cãi về điều đó :) Nhưng theo quan điểm của tôi về kỹ thuật quá mức và bất ngờ (theo nghĩa toán học). Bạn học sth từ lớp 2 hoặc 3 trở đi và đột nhiên một số kỹ sư biên dịch quyết định thay đổi logic toán học .. .. và máy tính dành cho con người không ngược lại. Thói quen của con người khó thay đổi. Chỉ là một ý kiến ​​khiêm tốn :) – sakhunzai

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