我想测试一个双精度为 3 或更少的最大精度。在 Java 中执行此操作的最佳方法是什么?
20.44567567 <- Fail
20.444 <- Pass
20.1 <- Pass
20 <- Pass
1)不要使用double
。浮点逻辑充其量是近似的。改为使用BigDecimal
。
2)我认为BigDecimal
已经有一种设置精度的方法。如果没有,只需乘以 1000 并截断。做操作,得到一个新的数字,和原来的比较。如果不同,则失败。
这通过了您的测试:
package com.sandbox;
import org.junit.Test;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
public class SandboxTest {
@Test
public void testPrecision() {
assertFalse(precisionLessThanOrEqualTo3(20.44567567));
assertTrue(precisionLessThanOrEqualTo3(20.444));
assertTrue(precisionLessThanOrEqualTo3(20.1));
assertTrue(precisionLessThanOrEqualTo3(20));
}
private boolean precisionLessThanOrEqualTo3(double x) {
return String.valueOf(x).replaceAll(".*\\.", "").length() <= 3;
}
}
您可以使用以下代码:
boolean f (double in){
if (in*1000 > (float)(int)(in*1000))
return false;
return true;
}
术语“精度”有多种可能的解释:
NUMBER(6,2)
列将存储最多 6 位的数字,这些数字始终由 2 位小数和 4 位整数组成。对于您的示例,您似乎将精度测量为最大小数位数。
这些中的每一个都可以使用以下方法进行测试:
import java.math.BigDecimal;
import org.junit.Test;
import static org.junit.Assert.*;
public class Precision
{
/**
* Tests to see whether the number has up to the given number of
* decimal places.
*
* @param value The value to test.
* @param scale The maximum number of decimal places.
* @return <code>true</code> if the value has up to the
* expected number of decimal places.
*/
static final boolean hasDecimalPlaces(
final double value,
final int scale
)
{
try
{
new BigDecimal( Double.toString( value ) ).setScale( scale );
return true;
}
catch ( final ArithmeticException ex )
{
return false;
}
}
/**
* Tests to see whether the number has up to the given number of
* significant figures.
*
* @param value The value to test.
* @param precision The maximum number of significant figures to
* test for.
* @return <code>true</code> if the value has up to the
* expected number of significant figures.
*/
static final boolean hasSignificantFigures(
final double value,
final int precision
)
{
try
{
return new BigDecimal( Double.toString( value ) ).stripTrailingZeros().precision() <= precision;
}
catch ( final ArithmeticException ex )
{
return false;
}
}
/**
* Tests to see whether the number has at most the given number of
* decimal places and, when represented at that maximum number of
* decimal places, has up to the given number of digits.
*
* @param value The number to test.
* @param precision The maximum number of digits to test for.
* @param scale The maximum number of decimal places.
* @return <code>true</code> if the value can be represented
* at the given scale and, at that scale, is up to
* the given precision.
*/
static final boolean hasDigitsAtScale(
final double value,
final int precision,
final int scale
)
{
try
{
return new BigDecimal( Double.toString( value ) ).setScale( scale ).precision() <= precision;
}
catch ( final ArithmeticException ex )
{
return false;
}
}
@Test
public void testScale(){
assertTrue( hasDecimalPlaces( 20d, 3 ) );
assertTrue( hasDecimalPlaces( 20.123d, 3 ) );
assertFalse( hasDecimalPlaces( 20.1234d, 3 ) );
}
@Test
public void testPrecision(){
assertTrue( hasSignificantFigures( 20d, 3 ) );
assertTrue( hasSignificantFigures( 120d, 3 ) );
assertTrue( hasSignificantFigures( 1230d, 3 ) );
assertFalse( hasSignificantFigures( 12340d, 3 ) );
assertTrue( hasSignificantFigures( 20.1d, 3 ) );
assertFalse( hasSignificantFigures( 20.12d, 3 ) );
assertTrue( hasSignificantFigures( 0.123d, 3 ) );
assertFalse( hasSignificantFigures( 0.1234d, 3 ) );
assertTrue( hasSignificantFigures( 0.0000999d, 3 ) );
assertFalse( hasSignificantFigures( 0.00009999d, 3 ) );
}
@Test
public void testPrecisionAndScale(){
assertTrue( hasDigitsAtScale( 0d, 3, 0 ) );
assertFalse( hasDigitsAtScale( 0.01d, 3, 0 ) );
assertFalse( hasDigitsAtScale( 0.1d, 3, 0 ) );
assertTrue( hasDigitsAtScale( 1d, 3, 0 ) );
assertTrue( hasDigitsAtScale( 10d, 3, 0 ) );
assertTrue( hasDigitsAtScale( 100d, 3, 0 ) );
assertFalse( hasDigitsAtScale( 1000d, 3, 0 ) );
assertFalse( hasDigitsAtScale( 10000d, 3, 0 ) );
assertTrue( hasDigitsAtScale( 0d, 3, 1 ) );
assertFalse( hasDigitsAtScale( 0.01d, 3, 1 ) );
assertTrue( hasDigitsAtScale( 0.1d, 3, 1 ) );
assertTrue( hasDigitsAtScale( 1d, 3, 1 ) );
assertTrue( hasDigitsAtScale( 10d, 3, 1 ) );
assertFalse( hasDigitsAtScale( 100d, 3, 1 ) );
assertFalse( hasDigitsAtScale( 1000d, 3, 1 ) );
assertFalse( hasDigitsAtScale( 10000d, 3, 1 ) );
assertTrue( hasDigitsAtScale( 0d, 3, -1 ) );
assertFalse( hasDigitsAtScale( 0.01d, 3, -1 ) );
assertFalse( hasDigitsAtScale( 0.1d, 3, -1 ) );
assertFalse( hasDigitsAtScale( 1d, 3, -1 ) );
assertTrue( hasDigitsAtScale( 10d, 3, -1 ) );
assertTrue( hasDigitsAtScale( 100d, 3, -1 ) );
assertTrue( hasDigitsAtScale( 1000d, 3, -1 ) );
assertFalse( hasDigitsAtScale( 10000d, 3, -1 ) );
}
}