Làm cách nào để kiểm tra xem số 0 là số dương hay số âm?


77

Có thể kiểm tra xem a floatlà số 0 dương (0.0) hay số 0 âm (-0.0) không?

Tôi đã chuyển đổi floatthành a Stringvà kiểm tra xem đầu tiên charcó phải là a hay không '-', nhưng có bất kỳ cách nào khác không?


8
Kiểm tra bit dấu (bit ngoài cùng bên trái) là đủ
boxed__l

6
Thật vậy, số không không âm cũng không phải là số dương.
Grijesh Chauhan

21
@GrijeshChauhan: Chỉ về mặt lý thuyết
Con vịt đang rên rỉ vào

10
@fridge: nhưng câu hỏi không phải về toán học, mà là về Java. Bất kỳ mối quan hệ mà các giá trị dấu chấm động có thể chịu đến các số là do thiết kế của con người và có khả năng trừu tượng rò rỉ ;-)
Steve Jessop

3
Có thể là một câu hỏi ngu ngốc, nhưng tôi chỉ tự hỏi: Tại sao người ta cần phải phân biệt giữa số dương và số 0 âm?
siegi

Câu trả lời:


80

Có, chia cho nó. 1 / +0.0f+Infinity, nhưng 1 / -0.0f-Infinity. Thật dễ dàng để tìm ra nó là cái nào bằng một phép so sánh đơn giản, vì vậy bạn sẽ nhận được:

if (1 / x > 0)
    // +0 here
else
    // -0 here

(điều này giả định rằng đó xchỉ có thể là một trong hai số 0)


6
Sẽ không dễ dàng hơn để chuyển dấu của số 0 sang một số khác, chẳng hạn như 1.0, với Math.copySign? Ví dụif (math.copySign (1.0, x) < 0.0) ...
njuffa

3
@njuffa: Không chắc math.copySign(1.0,x)<0.0là "dễ" hơn như thế nào 1/x>0. Ý tôi là cả hai đều khá khó giải thích, vì vậy dù sao bạn cũng muốn có một chức năng cho việc đó
Niklas B.

2
@njuffa: Vâng, tôi nghĩ bạn có thể đọc các vấn đề với câu trả lời này;) Tôi đã không xem xét chia sẽ là nặng, vì có lẽ là một trường hợp đặc biệt cho zero ước nào
Niklas B.

1
Nếu các bạn muốn xem nó nặng đến mức nào thì .. tùy. Ví dụ: việc chuyển dấu hiệu gây khó chịu khi thực hiện với hướng dẫn x87, nhưng tuyệt vời với SSE. Và quá trình phân chia mất bao lâu, khoảng từ 9 (tôi nghĩ?) Đến hơn một trăm chu kỳ (tùy thuộc vào các giá trị được chia và µarch). Một trong hai người có thể thắng, và đó chỉ là trên các hệ thống x86.
harold

1
Nếu bạn chỉ muốn hiệu quả, không phải chuyển đổi nó thành int và thẩm vấn bit dấu có phải là giải pháp tốt nhất? Tôi không chắc bạn có thể làm điều đó hiệu quả như thế nào trong Java, nhưng trên hầu hết các kiến ​​trúc, điều đó có thể được thực hiện đơn giản với lệnh OR theo sau là lệnh nhảy số 0 hoặc lệnh nhảy không phải bằng 0 và lệnh OR thường là chu kỳ đơn. Tuy nhiên, chi phí nhảy có điều kiện thay đổi rất nhiều theo kiến ​​trúc.
reirab

39

Bạn có thể sử dụng Float.floatToIntBitsđể chuyển đổi nó thành một intvà nhìn vào mẫu bit:

float f = -0.0f;

if (Float.floatToIntBits(f) == 0x80000000) {
    System.out.println("Negative zero");
}

Tốt hơn nhiều so với việc chia, có thể mất vài chu kỳ đồng hồ và có thể bẫy tình trạng tràn trong đơn vị FPU. Tốt hơn:(Float.floatToIntBits(f) & 0x80000000) < 0
Mark Jeronimus

12

Rõ ràng không phải là cách tiếp cận tốt nhất. Kiểm tra chức năng

Float.floatToRawIntBits(f);

Doku:

/**
 * Returns a representation of the specified floating-point value
 * according to the IEEE 754 floating-point "single format" bit
 * layout, preserving Not-a-Number (NaN) values.
 *
 * <p>Bit 31 (the bit that is selected by the mask
 * {@code 0x80000000}) represents the sign of the floating-point
 * number.
 ...
 public static native int floatToRawIntBits(float value);

10

Double.equalsphân biệt ± 0.0 trong Java. (Còn nữa Float.equals.)

Tôi hơi ngạc nhiên là không ai đề cập đến những điều này, vì đối với tôi chúng dường như rõ ràng hơn bất kỳ phương pháp nào được đưa ra cho đến nay!


Điều đó thực sự rõ ràng hơn; tuy nhiên, bạn có thể không muốn phân bổ hai Đối tượng trên heap chỉ để so sánh hai giá trị.
Klitos Kyriacou

7

Cách tiếp cận được sử dụng Math.mintương tự như những gì Jesper đề xuất nhưng rõ ràng hơn một chút:

private static int negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);

float f = -0.0f;
boolean isNegativeZero = (Float.floatToRawIntBits(f) == negativeZeroFloatBits);

6

Khi số float là số âm (bao gồm -0.0-inf), nó sử dụng cùng một bit dấu với số nguyên âm. Điều này có nghĩa là bạn có thể so sánh biểu diễn số nguyên với 0, loại bỏ sự cần thiết phải biết hoặc tính toán biểu diễn số nguyên của -0.0:

if(f == 0.0) {
  if(Float.floatToIntBits(f) < 0) {
    //negative zero
  } else {
    //positive zero
  }
}

Điều đó có thêm một nhánh đối với câu trả lời được chấp nhận, nhưng tôi nghĩ nó dễ đọc hơn nếu không có hằng số hex.

Nếu mục tiêu của bạn chỉ là coi -0 là số âm, bạn có thể bỏ ifcâu lệnh bên ngoài :

if(Float.floatToIntBits(f) < 0) {
  //any negative float, including -0.0 and -inf
} else {
  //any non-negative float, including +0.0, +inf, and NaN
}

0

Đối với tiêu cực:

new Double(-0.0).equals(new Double(value));

Đối với tích cực:

new Double(0.0).equals(new Double(value));
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.