Java中最高精度的测试编号

时间:2013-03-29 20:00:51

标签: java precision

我想测试一个double,最大精度为3或更小。在Java中执行此操作的最佳方法是什么?

20.44567567 <- Fail
20.444 <- Pass
20.1 <- Pass
20 <- Pass

4 个答案:

答案 0 :(得分:4)

1)不要使用double。浮点逻辑最多是近似的。请改用BigDecimal

2)我认为BigDecimal已经有了设定精度的方法。如果没有,只需乘以1000并截断。执行操作,获取新编号,并与原始编号进行比较。如果不同,则失败。

答案 1 :(得分:1)

这通过了你的测试:

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;
    }
}

答案 2 :(得分:1)

您可以使用以下代码:

boolean f (double in){
    if (in*1000 > (float)(int)(in*1000))
        return false;
    return true;
}

答案 3 :(得分:0)

"precision"一词有多种可能的解释:

  • 算术精度是有效数字的总数(小数点前后)。
  • 数字的小数部分(或小数位数)中的位数。
  • 尤其是在数据库中,可以使用计数中包含的固定小数位数(小数位数)来测量精度,因此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 ) );
  }
}