16

Tôi thường cần đặt sàn hoặc trần một số CGFloat đến một số int để tính chỉ mục mảng.Làm thế nào để an toàn sàn hoặc ceil một CGFloat để int?

Sự cố tôi thấy vĩnh viễn với floorf(theCGFloat) hoặc ceilf(theCGFloat) là có thể có vấn đề với điểm không chính xác.

Vì vậy, nếu CGFloat của tôi là 2.0f nhưng nội bộ nó được thể hiện là 1.999999999999f hoặc thứ gì đó tương tự. Tôi làm floorf và nhận được 1.0f, đó là một phao một lần nữa. Tuy nhiên, tôi phải bỏ con thú này để int có thể giới thiệu một vấn đề khác.

Có một thực hành tốt nhất làm thế nào để sàn hoặc Ceil một float một int như một cái gì đó giống như 2.0 sẽ không bao giờ vô tình được làm mức sàn cho 1 và một cái gì đó giống như 2.0 sẽ không bao giờ vô tình được ceiled để 2?

+4

Câu hỏi này không thể trả lời một cách chính xác cho đến khi thông số kỹ thuật được cung cấp mô tả lỗi trong giá trị đầu vào và những gì hậu quả là các giá trị mà quá trở về cao hay quá thấp. Có sự cân bằng giữa trả về giá trị quá cao vì lỗi làm tròn trước đó làm cho giá trị quá cao và trả lại giá trị quá thấp vì giá trị được điều chỉnh giả tạo để bù cho lỗi trước đó và ngược lại. Không có giải thích về ngữ cảnh, không có câu trả lời đúng nào. –

Trả lời

19

Có một vài quan niệm sai lầm trong câu hỏi của bạn.

gì nếu CGFloat của tôi là 2.0f nhưng nội nó được biểu diễn dưới dạng 1.999999999999f

không thể xảy ra; 2.0, giống như tất cả các số nguyên hợp lý nhỏ, có biểu diễn chính xác trong dấu phẩy động. Nếu số CGFloat của bạn là 2.0f thì thực sự là 2.0.

cái gì đó như 2.0 sẽ không bao giờ vô tình được ceiled đến 2

Mức trần 2,0 2; những gì khác nó sẽ có thể được?


Tôi nghĩ câu hỏi rằng bạn đang thực sự yêu cầu là "cho rằng tôi làm một phép tính mà tạo ra một kết quả không chính xác, mà về mặt toán học nên được chính xác 2.0, nhưng thực sự là một chút ít, khi tôi áp dụng floor để giá trị đó, tôi nhận được 1.0 thay vì 2.0 - làm thế nào để ngăn chặn điều này?"

Đó thực sự là một câu hỏi khá tế nhị mà không có một đĩa đơn 'đúng' câu trả lời. Làm thế nào bạn đã tính toán các giá trị đầu vào? Bạn sẽ làm gì với kết quả?

1

EDIT - đọc các ý kiến ​​cho lý do tại sao câu trả lời này là không đúng :)

Đúc một float một int là một tiềm ẩn floorf ví dụ (int)5.95. Nếu bạn không nhớ rằng sau đó chỉ cần bỏ :)

Nếu bạn muốn làm tròn thì chỉ cần đưa kết quả ceilf - truyền sau khi làm tròn sẽ không giới thiệu bất kỳ lỗi nào (hoặc, nếu bạn muốn, thêm một trước khi đúc tức là `(int) (5.9 + 1) 'là' 6 '- giống như làm tròn lên).

Để làm tròn gần nhất, chỉ cần thêm 0,5 - (int)(5.9+0.5)6 nhưng (int)(5.4+0.5)5. Mặc dù tôi chỉ sử dụng roundf(5.9) :)

+8

Đúc phao vào int không phải là một sàn ngầm. Đó là, trong C và một số ngôn ngữ phổ biến khác, một cắt ngắn (về phía không). Sàn làm tròn đến số nguyên gần nhất theo hướng vô cực âm. Chuyển đổi -3.5 thành sản lượng nguyên -3, nhưng sàn (-3.5) là -4. –

+0

OK, đó là một điểm công bằng - Tôi đã đơn giản hóa đến mức sai lầm :) – deanWombourne

18

câu trả lời bổ sung Swift

tôi thêm này như một câu trả lời bổ sung cho những ai đến đây tìm cách sử dụng floorceil với một CGFloat (như tôi đã làm).

var myCGFloat: CGFloat = 3.001 
floor(myCGFloat) // 3.0 
ceil(myCGFloat) // 4.0 

Và nếu cần Int thì có thể truyền thành một.

var myCGFloat: CGFloat = 3.001 
Int(floor(myCGFloat)) // 3 
Int(ceil(myCGFloat)) // 4 

Cập nhật

Không có nhu cầu sử dụng C floorceil chức năng nữa. Bạn có thể sử dụng Swift round() với rounding rules.

var myCGFloat: CGFloat = 3.001 
myCGFloat.round(.down) // 3.0 
myCGFloat.round(.up) // 4.0 

Nếu bạn không muốn sửa đổi biến ban đầu, thì hãy sử dụng rounded().

Ghi chú

  • trình với cả hai kiến ​​trúc 32 và 64 bit.

Xem thêm

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