Calculating double neighbours of a decimal value

我与影子孤独终老i 提交于 2019-12-24 07:37:41

问题


The code:

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

The output:

0.1000000000000000055511151231257827021181583404541015625 0.6999999999999999555910790149937383830547332763671875

This is nice because it lets me find a double that is the closest to given value. But as for 0.1 a value is bigger and for 0.7 value is smaller than real value.

How can I get both values (closest bigger and closest smaller) for any decimal number?

Assume I start with BigDecimal, then convert it do a double and then back to decimal. I'll get bigger or smaller value. How could I got the other?


回答1:


Use 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"));
  }
}

Printout:

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:


The Math.ulp(double) method might be useful for this, it returns something like the possible floating point precision for the given value:

Returns the size of an ulp of the argument. An ulp of a double value is the positive distance between this floating-point value and the double value next larger in magnitude. Note that for non-NaN x, ulp(-x) == ulp(x).

Here is an example:

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:


Create BigDecimal based on Integer or on String:

// String:
BigDecimal a = new BigDecimal("0.1");

// Integer
BigDecimal b = (new BigDecimal(7)).movePointLeft(1);

It will not give you such results.



来源:https://stackoverflow.com/questions/10637594/calculating-double-neighbours-of-a-decimal-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!