【问题标题】:Calculating double neighbours of a decimal value计算十进制值的双邻居
【发布时间】:2012-05-17 14:24:27
【问题描述】:

代码:

import java.math.*; 

public class x
{
  public static void main(String[] args)
  {
    BigDecimal a = new BigDecimal(0.1);
    BigDecimal b = new BigDecimal(0.7);
    System.out.println(a);
    System.out.println(b);
  }
}

输出:

0.1000000000000000055511151231257827021181583404541015625 0.6999999999999999555910790149937383830547332763671875

这很好,因为它可以让我找到最接近给定值的double。 但是0.1 的值更大,0.7 的值小于实际值。

如何获得任何十进制数的两个值(最接近的大和最接近的小)?

假设我以BigDecimal 开头,然后将其转换为double,然后再转换回十进制。我会得到更大或更小的价值。我怎么能得到另一个?

【问题讨论】:

  • 如果您以double 开头,我怀疑这是可能的。当您的程序看到您输入的内容为0.1 时,该值已经变为0.100000000000000005...。程序无法知道它的舍入方式(因为它无法知道原始值)。希望这是有道理的。

标签: java floating-point bigdecimal


【解决方案1】:

使用nextAfter(double start, double direction):

import java.math.*;

public class a
{
  public static void printNeighbours(BigDecimal start)
  {
    double result1 = start.doubleValue();
    double result2;

    BigDecimal r1 = new BigDecimal(result1);

    int com = start.compareTo(r1);

    if(com != 0)
      result2 = Math.nextAfter(result1, com * Double.MAX_VALUE);
    else
    {
      result2 = Math.nextAfter(result1, Double.MAX_VALUE);
      result1 = Math.nextAfter(result1, -Double.MAX_VALUE);
      r1 = new BigDecimal(result1);
    }

    BigDecimal r2 = new BigDecimal(result2);

    System.out.println("starting:\t"+start);

    if(com<0)
    {
      System.out.println("smaller:\t" + r2);        
      System.out.println("bigger:\t\t"+r1);
    }
    else
    {
      System.out.println("smaller:\t" + r1);        
      System.out.println("bigger:\t\t"+r2);
    }

    System.out.println();
  }

  public static void main(String[] args)
  {
    printNeighbours(new BigDecimal("0.25"));
    printNeighbours(new BigDecimal("0.1"));
    printNeighbours(new BigDecimal("0.7"));
  }
}

打印输出:

starting:   0.25
smaller:    0.2499999999999999722444243843710864894092082977294921875
bigger:     0.250000000000000055511151231257827021181583404541015625

starting:   0.1
smaller:    0.09999999999999999167332731531132594682276248931884765625
bigger:     0.1000000000000000055511151231257827021181583404541015625

starting:   0.7
smaller:    0.6999999999999999555910790149937383830547332763671875
bigger:     0.70000000000000006661338147750939242541790008544921875

【讨论】:

    【解决方案2】:

    Math.ulp(double) 方法可能对此很有用,它返回类似于给定值可能的浮点精度:

    返回参数的 ulp 的大小。双精度值的 ulp 是该浮点值与幅度下一个更大的双精度值之间的正距离。请注意,对于非 NaN x,ulp(-x) == ulp(x)。

    这是一个例子:

    System.out.println(new BigDecimal(0.1).subtract(new BigDecimal(Math.ulp(0.1))));
    System.out.println(new BigDecimal(0.7).add(new BigDecimal(Math.ulp(0.7))));
    

    【讨论】:

      【解决方案3】:

      基于整数或字符串创建 BigDecimal:

      // String:
      BigDecimal a = new BigDecimal("0.1");
      
      // Integer
      BigDecimal b = (new BigDecimal(7)).movePointLeft(1);
      

      它不会给你这样的结果。

      【讨论】:

        猜你喜欢
        • 2022-10-13
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-29
        • 1970-01-01
        相关资源
        最近更新 更多