Tại sao Math.Floor (Double) trả về giá trị kiểu Double?


103

Tôi cần lấy giá trị số nguyên bên trái từ số thập phân hoặc kép. Đối với Ví dụ: Tôi cần lấy giá trị 4 từ 4,6. Tôi đã thử sử dụng hàm Math.Floor nhưng nó trả về giá trị gấp đôi, ví dụ: Nó trả về 4.0 từ 4.6. Tài liệu MSDN nói rằng nó trả về một giá trị số nguyên. Am i thiếu cái gì ở đây? Hay có một cách khác để đạt được những gì tôi đang tìm kiếm?


2
Tài liệu MSDN nói rằng nó trả về một giá trị số nguyên . Tài liệu MSDN nói rằng Math.Floor trả về System.Double, không phải số nguyên.
băng thông rộng

Một giá trị số nguyên thực sự cần thiết, nhưng nó không có nghĩa là nó có thể được lưu trữ trong một "int" hoặc "long". "Double" lưu trữ thành công tất cả các giá trị số nguyên trong một phạm vi rộng hơn nhiều so với chỉ "int" Lưu ý rằng một số giá trị số nguyên có thể được làm tròn khi phần định trị không có đủ bit để lưu trữ tất cả các chữ số của giá trị số nguyên, khi số mũ cơ số 2 của nó vượt lên trên 52: việc làm tròn các giá trị nguyên trong "double" có thể xảy ra đối với các số nguyên trên 2 ^ 52 hoặc dưới -2 ^ 52 nhưng kết quả sẽ vẫn là số nguyên gần nhất có thể biểu diễn; nếu bạn sử dụng "(dài) Tầng (x)", chuyển đổi có thể sai phần lớn.
verdy_p

Tuy nhiên, lưu ý rằng phạm vi hợp lệ của các vallue số nguyên có thể được biểu diễn trong một "kép" là cực kỳ lớn, với các giá trị tuyệt đối lên đến: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1.7976931348623157E308; nó là nhiều hơn 2 ^ 63-1 với "dài". Tuy nhiên, phạm vi của tất cả các số nguyên có thể được lưu trữ riêng biệt bị hạn chế hơn, bởi vì "double" chỉ có 52 bit cho phần định trị (cộng với 1 bit ngụ ý cho bit quan trọng nhất, không được lưu trữ), có nghĩa là "double" chỉ có thể lưu trữ số nguyên chỉ chính xác khi giá trị tuyệt đối của chúng nhỏ hơn 2 ^ 53.
verdy_p

Thật không may, Math.Floor () không trả về kiểu "Số" trong nội bộ bằng cách sử dụng "Dài" nếu có thể hoặc "Đôi" nếu không, chỉ cho các số nguyên làm tròn lớn. Và thư viện Math tiêu chuẩn không xử lý kiểu số biến thống nhất như vậy. Tồn tại các thư viện toán học khác triển khai kiểu số thống nhất, bao gồm cả số nguyên Dài, gấp đôi hoặc lớn được mã hóa ở dạng thập phân hoặc nhị phân đóng gói mà không làm mất phạm vi hoặc độ chính xác được hỗ trợ.
verdy_p

Câu trả lời:


146

Phạm vi của doublerộng hơn nhiều so với phạm vi của inthoặc long. Hãy xem xét mã này:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

Số nguyên nằm ngoài phạm vi long- vì vậy bạn mong đợi điều gì sẽ xảy ra?

Thông thường, bạn biết rằng giá trị thực sự sẽ nằm trong phạm vi inthoặc long, vì vậy bạn truyền nó:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

nhưng nguyên nhân của dàn diễn viên đó là ở nhà phát triển, không phải ở Math.Floorchính nó. Nó sẽ là hạn chế không cần thiết để làm cho nó chỉ bị lỗi với một ngoại lệ cho tất cả các giá trị nằm ngoài phạm vi của long.


2
Tầng trả về biểu diễn số nguyên của double và nó trả về double cho các phép tính khoa học, câu trả lời này không đúng vì double có 64 bit và long cũng có 64 bit, nhưng double không thể lưu trữ các chữ số chính xác của các bit có nghĩa thấp hơn ngay cả khi nó có thể được lưu trữ chính xác trong thời gian dài.
Akash Kava

1
@ Jon: làm thế nào mà bạn chưa cân nhắc về các cuộc tranh luận dữ dội về cách để thực hiện một âm dương số trong C # ?: stackoverflow.com/questions/1348080/...
MusiGenesis

3
@Jon: mất thời gian của bạn. Hóa ra cộng đồng đã phát hiện ra rằng nhân một số dương với -1 sẽ làm cho nó âm. Tất cả đều tốt trên StackOverflow.
MusiGenesis

1
@javapowered: Không, (int) 15.0 không phải là 0. Một cái gì đó khác đã xảy ra, nhưng chúng tôi không thể biết điều gì từ điều đó. Vui lòng tạo một chương trình ngắn nhưng đầy đủ thể hiện điều này, rồi đặt câu hỏi. Tôi nghi ngờ bạn sẽ tìm thấy nó khó khăn để tái sản xuất ...
Jon Skeet

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Khối lượng </code> được tính là <code> (int) 0,15 * Khối lượng </code>, nhưng kiểu chữ chỉ áp dụng cho tỷ lệ, không phải kết quả của sản phẩm và bạn nhận được <code> 0 * Volume </code> tức là bằng không! Thay vào đó, hãy sử dụng <code> (int) (IGNORE_RATIO * Volume) </code> để giải quyết lỗi của BẠN.
verdy_p

11

Theo MSDN, Math.Floor (double) trả về một double: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Nếu bạn muốn nó như một int:

int result = (int)Math.Floor(yourVariable);

Tôi có thể thấy bài viết MSDN có thể gây hiểu lầm như thế nào, lẽ ra họ phải chỉ định rằng mặc dù kết quả là "số nguyên" (trong trường hợp này có nghĩa là số nguyên), nó vẫn thuộc TYPE Double


Cảm ơn bạn đã trả lời. Trên thực tế, tôi đang xem bài viết này: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Nhưng dù sao, tôi sẽ thử gợi ý của bạn. Cảm ơn bạn.

Vâng đúng, nó nói ở đầu "trả về một số nguyên" nhưng loại được quy định dưới nó: public static Tầng đôi (double d)
Neil N

3
integer! = int( answers.com/integer ) - số nguyên có thể được lưu trữ trong Double(xem câu trả lời của Jon), và có vô số số nguyên không thể được lưu trữ trong một int.
Shog

Shog, tôi không nói rằng họ không thể. Những gì tôi đã nói là "nó vẫn thuộc loại TYPE Double"
Neil N

1
@Neil: phải - chỉ muốn nhấn mạnh sự khác biệt giữa "số nguyên" (tên của một tập hợp) và int(tên của một kiểu).
Shog

4

Nếu bạn chỉ cần phần nguyên của một số, hãy chuyển số đó thành an int. Thao tác này sẽ cắt bớt số ở dấu thập phân.

double myDouble = 4.6;
int myInteger = (int)myDouble;

2
Điều quan trọng cần lưu ý rằng truyền để inthoạt động khác với Floor, đối với số âm. Floorsẽ luôn luôn cắt ngắn với số tiêu cực nhất, trong khi đúc để intsẽ truncate hướng 0.
Magnus


0

Tầng để lại nó như một nhân đôi để bạn có thể thực hiện nhiều phép tính gấp đôi với nó. Nếu bạn muốn nó là một int, hãy ép kiểu kết quả của tầng dưới dạng một int. Không ép cặp ban đầu dưới dạng số nguyên vì các quy tắc về tầng khác nhau (IIRC) đối với số âm.


0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

Điều này sẽ cung cấp cho bạn giá trị chính xác mà bạn muốn nếu bạn lấy 4.6nó trả về 4làm đầu ra.

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.