Tôi đang sử dụng đoạn mã sau để chuyển đổi một thập lục phân String
đến một điểm nổi String
:Hexadecimal -> Float chuyển đổi không chính xác
private static String removeScientificNotation(float value)
{
return new BigDecimal(Float.toString(value)).toPlainString();
}
/**
* Converts a hexadecimal value to its single precision floating point representation
*
* @param hexadecimal The <code>hexadecimal</code> to convert
* @return The converted value
*/
public static String hexadecimalToFloatingPoint(String hexadecimal)
{
Long longBits = Long.parseLong(hexadecimal, 16);
Float floatValue = Float.intBitsToFloat(longBits.intValue());
return removeScientificNotation(floatValue);
}
Để kiểm tra điều này, tôi đã viết JUnit
thử nghiệm sau đây:
public class TestConversions
{
@Test
public void testConversions()
{
String floatValue = Conversions.hexadecimalToFloatingPoint("40000000");
Assert.assertEquals(floatValue, "2.0");
floatValue = Conversions.hexadecimalToFloatingPoint("50000000");
Assert.assertEquals(floatValue, "8589934592");
floatValue = Conversions.hexadecimalToFloatingPoint("C0000000");
Assert.assertEquals(floatValue, "-2.0");
}
}
Tuy nhiên, xác nhận thứ 2 không thành công. Theo nhiều người chuyển đổi trực tuyến khác nhau như this one, 50000000
phải được chuyển đổi thành 8589934592
nhưng Java trả lại 8589934600
.
org.junit.ComparisonFailure:
Expected :8589934600
Actual :8589934592
Kết quả nào là chính xác? Nếu Java sai thì làm thế nào để sửa nó?
Tôi nghi ngờ những gì bạn thấy là chỉ có 7 chữ số chính xác đáng kể nên được dựa vào 'float' ... (Thử trả về' float' thay vì 'String' và so sánh kết quả của bạn với 8589934600f) –
Lưu ý rằng * giá trị float chính xác gần nhất * tới 8589934600 là 8589934592. –
Đó là lý do tại sao bạn không nên so sánh chính xác với phao nổi. Đối với các xác nhận trong các phép thử đơn vị, có 'Assert # equals (floatA, floatB, delta)'. –