2009-04-17 42 views
17

Tôi có thể so sánh số dấu phẩy động với số nguyên không?Tôi có thể so sánh và thêm một số dấu phẩy động vào một số nguyên trong C không?

Biến nổi có so sánh với số nguyên trong mã không?

float f;  // f has a saved predetermined floating-point value to it 
if (f >=100){__asm__reset...etc} 

Ngoài ra, có thể tôi ...

float f; 
int x = 100; 
x+=f; 

tôi phải sử dụng giá trị dấu chấm động f nhận được từ một hệ thống tham chiếu thái độ để điều chỉnh giá trị vị trí x điều khiển một PWM tín hiệu để sửa cho thái độ.

Trả lời

18

Cái đầu tiên sẽ hoạt động tốt. 100 sẽ được chuyển thành một phao và IEE754 có thể đại diện cho tất cả các số nguyên chính xác như phao, lên đến khoảng 2 .

Điều thứ hai cũng sẽ hoạt động nhưng sẽ được chuyển thành số nguyên đầu tiên, vì vậy bạn sẽ mất độ chính xác (điều đó là không thể tránh khỏi nếu bạn đang chuyển nổi thành số nguyên).

+0

Cảm ơn, vì vậy điều đó có nghĩa là nếu f = 1.0162 nó sẽ là int f == 1, vì vậy tôi sẽ chỉ phải mở rộng nó, f * = 1000; vì vậy int f == 1016 để giữ lại độ chính xác? – sevenboarder

+0

Bạn không thể đại diện cho tất cả các số nguyên chính xác như phao. Không phải với mantissa 24-bit của phao. Nếu nó là gấp đôi, có, nhưng không nổi :) – Joey

+0

@Johannes, bạn nói đúng, tôi đang ghi nhớ sai một câu hỏi tôi đã trả lời gần đây, cập nhật để sửa chữa. – paxdiablo

0

Vâng, nó sẽ hoạt động tốt. Cụ thể, int sẽ được chuyển thành float cho mục đích chuyển đổi. Trong thứ hai, bạn sẽ cần phải cast vào int nhưng nó sẽ là tốt nếu không.

1

LHS xác định độ chính xác, Vì vậy, nếu LHS của bạn là int và RHS là nổi, sau đó điều này dẫn đến mất độ chính xác.

Ngoài ra hãy xem tại FP liên quan CFAQ

0

Vâng, và đôi khi nó sẽ làm chính xác những gì bạn mong đợi.

Như những người khác đã chỉ ra, so sánh, ví dụ: 1.0 == 1 sẽ hoạt động, vì số nguyên 1 được nhập thành double (không phải float) trước khi so sánh.

Tuy nhiên, các so sánh khác có thể không.

1

Có, bạn có thể so sánh chúng, bạn có thể làm toán trên chúng mà không cần phải quan tâm nhiều đến đâu, trong hầu hết các trường hợp. Nhưng chỉ nhiều nhất. Các bugaboo lớn là bạn có thể kiểm tra f<i vv nhưng không nên kiểm tra f==i. Một số nguyên và một phao mà 'phải' giống hệt nhau về giá trị không nhất thiết phải giống hệt nhau.

2

Bạn có thể so sánh phao và số nguyên không. Nhưng vấn đề bạn sẽ gặp phải là chính xác. Trên hầu hết các triển khai C/C++, float và int có cùng kích thước (4 byte) và các mức độ chính xác khác nhau cực kỳ khác nhau. Không loại nào có thể chứa tất cả các giá trị của loại khác. Vì một loại không thể được chuyển đổi sang loại khác mà không mất độ chính xác và các loại không thể so sánh được với bản địa, việc so sánh mà không xem xét loại khác sẽ dẫn đến mất chính xác trong một số trường hợp.

Những gì bạn có thể làm để tránh mất chính xác là chuyển đổi cả hai loại thành loại có đủ độ chính xác để biểu diễn tất cả các giá trị của float và int. Trên hầu hết các hệ thống, đôi sẽ làm điều đó.Vì vậy, sau thường làm một sự so sánh không tổn hao

float f = getSomeFloat(); 
int i = getSomeInt(); 
if ((double)i == (double)f) { 
    ... 
} 
+3

Tôi nghĩ bạn muốn "> =" (để khớp với câu hỏi gốc) chứ không phải "==". Thử nghiệm cho sự bình đẳng chính xác của các số dấu phẩy động là hầu như luôn luôn là một ý tưởng tồi. –

10

Vì bạn đã xác định mình là không quen với sự tinh tế của số dấu chấm động, tôi sẽ giới thiệu bạn đến giấy phạt này bởi David Goldberg: What Every Computer Scientist Should Know About Floating-Point Arithmetic (reprint tại Mặt trời).

Sau khi bạn đã lo sợ về điều đó, thực tế là hầu hết điểm nổi thời gian là một lợi ích rất lớn để thực hiện các phép tính. Và các trình biên dịch và ngôn ngữ hiện đại (bao gồm cả C) xử lý các chuyển đổi một cách hợp lý để bạn không phải lo lắng về chúng. Trừ khi bạn làm.

Điểm được nêu về độ chính xác chắc chắn là hợp lệ. An IEEE float hiệu quả chỉ có 24 bit chính xác, ít hơn số nguyên 32 bit. Sử dụng double để tính toán trung gian sẽ đẩy tất cả làm tròn và mất chính xác ra chuyển đổi trở lại float hoặc int.

+0

+1 cho liên kết WECSSKAFPA, điều đó đã giúp tôi không thể lướt web. :) – unwind

+0

Tôi đã cho giấy một skim, tôi có thể đặt nó cho đến sau này ...haha – sevenboarder

+0

Đó là một chút nặng về toán học ... nhưng bạn có thể lướt qua tất cả các bằng chứng và nhận được những điểm quan trọng. Điểm quan trọng lớn chỉ là nó không phải là luôn luôn đơn giản ... – RBerteig

8

Số học chế độ hỗn hợp (số học giữa các toán hạng của các loại và/hoặc kích thước khác nhau) là hợp pháp nhưng mong manh. Tiêu chuẩn C định nghĩa các quy tắc cho quảng cáo loại để chuyển đổi các toán hạng thành một biểu diễn chung. Tự động loại khuyến mãi cho phép trình biên dịch để làm một cái gì đó hợp lý cho các hoạt động chế độ hỗn hợp, nhưng "hợp lý" không nhất thiết có nghĩa là "chính xác".

Để thực sự biết liệu hành vi có chính xác hay không, trước tiên bạn phải hiểu các quy tắc về quảng cáo và sau đó hiểu được sự đại diện của các loại dữ liệu. Trong thuật ngữ rất chung:

  • ngắn hơn các loại được chuyển đổi sang loại dài hơn (float để double, short để int, vv)
  • loại nguyên được chuyển đổi thành các loại dấu chấm động
  • ký/unsigned chuyển đổi ưu tiên tránh mất dữ liệu (cho dù đã ký được chuyển thành chưa ký hoặc ngược lại phụ thuộc vào kích thước của các loại tương ứng)

Cho dù mã như x > y (trong đó xy có các loại khác nhau) là đúng hay sai phụ thuộc vào các giá trị xy có thể thực hiện. Theo kinh nghiệm của tôi, thực tế phổ biến là cấm chuyển đổi kiểu ngầm (thông qua mã hóa tiêu chuẩn). Lập trình viên phải xem xét ngữ cảnh và thực hiện rõ ràng bất kỳ chuyển đổi loại nào cần thiết.

0

Về điều đó, ký hiệu 1.0 là loại gấp đôi để so sánh được thực hiện bằng gấp đôi theo các quy tắc quảng bá loại như đã nói trước đây. 1.f hoặc 1.0f là loại phao và so sánh sẽ được thực hiện trong phao. Và nó cũng đã hoạt động tốt kể từ khi chúng tôi nói rằng 2^23 số nguyên đầu tiên là đại diện trong một phao.

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