Truyền đến tầng int vs


120

Có sự khác biệt nào giữa những điều này:

float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);

Theo tôi hiểu, cả hai trường hợp đều có cùng một kết quả. Có sự khác biệt nào trong mã biên dịch không?


1
tốt hơn một chút với floor, nhưng hãy cẩn thận rằng điều này doublekhông phải dành cho float. C99 cũng có floorfcho float.
Jens Gustedt,

2
Vì vậy, họ có cùng một kết quả chừng nào thanh dương
Zac

1
(lưu ý: vui lòng #include<cmath>sử dụng trong C ++ std::floor)
user202729,

Loại là bargì?
chux - Phục hồi Monica

@chux Không thành vấn đề, dù sao chia cho 3.0 cũng sẽ khiến nó thành đôi
kaalus

Câu trả lời:


193

Truyền tới một int sẽ cắt ngắn về 0. floor()sẽ cắt ngắn về phía âm vô hạn. Điều này sẽ cung cấp cho bạn các giá trị khác nhau nếu barlà số âm.


15
Tôi nghĩ bạn đã đánh đinh vào đầu ở đây. Một sự khác biệt khác, nếu floor()là ý định, là nếu giá trị của barquá lớn để vừa với một int.
Fred Larson

Bạn có nguồn nào cho tuyên bố đó không?
HelloGoodbye

1
Ngay cả khi kết quả là dương tính, nó không được đảm bảo. Xem cái nàycái này .
user202729,

27

Như đã nói trước đây, đối với các số dương chúng giống nhau, nhưng chúng khác nhau đối với các số âm. Quy tắc là int làm tròn về phía 0, trong khi sàn làm tròn về phía âm vô cùng.

floor(4.5) = (int)4.5 = 4
floor(-4.5) = -5 
(int)(-4.5) = -4

Điều này đang được nói, cũng có sự khác biệt về thời gian thực hiện. Trên hệ thống của mình, tôi đã hẹn giờ rằng quá trình truyền nhanh hơn ít nhất 3 lần so với sàn.

Tôi có mã cần hoạt động sàn của một phạm vi giá trị giới hạn, bao gồm cả số âm. Và nó cần phải rất hiệu quả, vì vậy chúng tôi sử dụng hàm sau cho nó:

int int_floor(double x) 
{ 
    return (int)(x+100000) - 100000; 
}

Tất nhiên điều này sẽ không thành công đối với các giá trị rất lớn của x (bạn sẽ gặp phải một số vấn đề về tràn) và đối với các giá trị âm dưới -100000, v.v. Nhưng tôi đã kiểm tra tốc độ của nó nhanh hơn ít nhất 3 lần so với sàn, điều này thực sự rất quan trọng cho ứng dụng của chúng tôi. Hãy xem nó bằng một hạt muối, kiểm tra nó trên hệ thống của bạn, v.v. nhưng nó đáng để xem xét IMHO.


"Tôi đã đánh giá nó nhanh hơn ít nhất 3 lần so với sàn" -> OP đang sử dụng float, không phải double- có lẽ doublelà ứng dụng của bạn. Nếu ở C, hãy chắc chắn sử dụng floorf()với floats.
chux - Phục hồi Monica

@chux Tôi nghĩ lý do duy nhất có bất kỳ sự khác biệt nào là việc diễn viên cho phép tối ưu hóa thời gian biên dịch. Vì vậy, chuyển đổi đó thực sự có thể đã bị loại bỏ hoàn toàn trong quá trình thực thi.
ClydeTheGhost

9

SO 101, không thay đổi câu hỏi của bạn sau khi mọi người đã trả lời câu hỏi của bạn, thay vào đó hãy viết một câu hỏi mới.

Bạn nghĩ tại sao họ sẽ có cùng một kết quả?

float foo = (int)(bar / 3.0) //will create an integer then assign it to a float

float foo = fabs(bar / 3.0 ) //will do the absolute value of a float division

bar = 1.0

foo1 = 0;
foo2 = 0.33333...

1
Ý bạn là fabsgì Câu hỏi là về floor. Tầng của 0.33333... là 0.
Aaron Franke,

2
@AaronFranke câu hỏi ban đầu đã được sửa đổi. dường như rất nhiều có thể xảy ra trong 8 năm ;-) thông báo câu trả lời khác có cùng một tiền đề
AndersK

4

CHỈNH SỬA: Vì câu hỏi có thể đã được sửa đổi do nhầm lẫn giữa fabs()floor().

Đưa ra các dòng ví dụ câu hỏi ban đầu:

1.  float foo = (int)(bar / 3.0);

2.  float foo = fabs(bar / 3.0);

Sự khác biệt là nếu thanh là âm, kết quả sẽ âm với thanh đầu tiên nhưng dương với thanh thứ hai. Đầu tiên sẽ được cắt ngắn thành một số nguyên và thứ hai sẽ trả về giá trị thập phân đầy đủ bao gồm cả phần phân số.


3

Đúng. fabstrả về giá trị tuyệt đối của đối số của nó và việc ép kiểu thành int gây ra sự cắt ngắn của phép chia (xuống giá trị int gần nhất), vì vậy kết quả hầu như sẽ luôn khác nhau.


2

Có hai điểm khác biệt chính:

  1. Như những người khác đã chỉ ra, ép kiểu đến một số nguyên sẽ cắt ngắn về phía 0, trong khi floor()sẽ luôn cắt về phía âm vô cùng; đây là hành vi khác nhau đối với toán hạng âm.

  2. Dường như chưa có ai chỉ ra sự khác biệt khác - nếu đối số của bạn lớn hơn hoặc bằng MAX_INT+1(hoặc nhỏ hơn -MAX_INT-1) thì việc truyền đến một intsẽ dẫn đến việc các bit cao nhất bị bỏ (C, có thể là) hoặc hành vi không xác định ( C ++ và có thể là C). EG nếu của bạn intlà 32 bit, bạn sẽ chỉ có một bit dấu cộng với 31 bit dữ liệu. Vì vậy, sử dụng cái này với doublekích thước lớn sẽ tạo ra kết quả không mong muốn.


2.a. Điều kiện chính xác để chuyển đổi thành inttràn là đối số lớn hơn hoặc bằng INT_MAX+1. Một cách đối xứng, điều kiện cho dòng dưới là đối số thấp hơn hoặc bằng INT_MIN-1.
Pascal Cuoq

1
2.b. Tràn trong chuyển đổi từ dấu phẩy động thành số nguyên là hành vi không xác định trong C ++. Nó không "dẫn đến việc giảm các bit cao nhất". Xem (mặc dù nó được viết cho C): blog.frama-c.com/index.php?post/2013/10/09/…
Pascal Cuoq

0

(int) xlà một yêu cầu giữ phần nguyên của x(không có làm tròn ở đây)

fabs(x)= | x | để nó >= 0;

Ví dụ: (int) -3.5trả lại -3; fabs(-3.5)trả lại 3.5;

Nói chung, fabs (x) >= xvới mọi x;

x >= (int) x nếu x >= 0

x < (int) x nếu x < 0


x = -3 fabs (-3) = 3 (int) -3 = -3; Tôi nghĩ rằng sự bất bình đẳng cuối cùng vẫn tồn tại. Bạn có thể nói rõ hơn tại sao nó sai?
Paul Hoàng

Xin lỗi, ý tôi là -3,5, ví dụ bạn đưa ra. -3> -3.5
Dennis Zickefoose

3
Câu lệnh cuối cùng vẫn phải là "x <= int (x) nếu x <0", chứ không phải "x <(int) x nếu x <0": các số nguyên âm được giữ nguyên.
Tomasz Gandor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.