3

我正在尝试将随机双精度数转换为长整数而不舍入或截断它。首先,我将双精度数更改为字符串,以了解有多少小数位,然后将值更改为长整数。我的问题是最后一个小数位的数字并不总是正确的,我不知道原因以及如何更改它。这是代码:

            double z=(double) myRandom(1, 20);
    long test;
    String s = Double.toString(z);
    test=(long) (Math.pow(10, s.length()-s.indexOf(".")-1)*z);
    System.out.println("z: "+z);    
    System.out.println("double converted to long: "+test);

这就是输出:

电话:19.625014811604743

双转换为长:19625014811604744

d: 9.143326452202839

双转换为长:9143326452202838

d: 5.8964228376511105

双转换为长:58964228376511104

电话:15.045936360299917

双转换为长:15045936360299918

d: 14.147950026532694

双转换为长:14147950026532694

4

6 回答 6

3

编辑您当前的实现:

double z=(double) myRandom(1, 20);
String s = Double.toString(z); //convert to string (edited thanks to comments)
s = s.replaceAll(".", ""); //remove the period
long test = Long.parseLong(s); //convert to long

或者,如果您只是想要一个随机的Long,我建议您Random.nextLong()改用。

于 2013-08-07T18:22:30.107 回答
2

如果您的目标是获得一个随机长数字,那么我强烈建议您使用 Random.nextLong() 代替。

于 2013-08-07T18:19:54.690 回答
1

其他答案指出了如何解决此问题,但您的另一个问题是它为什么会发生。答案是浮点错误。

浮点数由三个主要部分组成:符号(+ 或 -)、尾数和指数。本质上,该数字基本上表示为(sign) (mantissa) * 2^(exponent)(但不完全是 - 请参阅下面的链接)。您可以想象,并非所有数字都适合这种表示形式。有些必须近似。典型的例子是十分之一,它在二进制中具有无限重复序列,因此必须用双精度来近似。

在高值——那些大于尾数可以表示的值——有一些整数不能精确表示。这发生在 2^53;任何大于此的数字都必须近似,您提到的数字就是这样的例子。

你甚至不需要Math.pow证明这一点;文字会做得很好。

public static void main(String[] args) {
  double d1 = 19.625014811604743;
  double d2 = 19625014811604743.0;

  System.out.println(d1);
  System.out.println(d2);
}

这将打印:

19.625014811604743
1.9625014811604744E16

请注意第二个值末尾的 4。19625014811604744 是最接近 19625014811604743 的数字,可以表示为双精度数。

相关阅读:

于 2013-08-08T15:51:08.070 回答
0
test=(long) (Math.pow(10, s.length()-s.indexOf(".")-1)*z);

在算术中弄乱了你的双倍,尝试这样的事情:

public long convertDoubleToLong(double d){
  String str = Double.toString(d);
  return Long.parseLong(str.replace(".", ""));
}
于 2013-08-07T18:23:39.477 回答
0

你可以做这样的事情......

double x = 19.625014811604743;
while(x % 1 != 0) x *= 10;
long y = (long) x;
System.out.println("x: "+ x + " y: "+ y);
于 2013-08-07T18:43:25.157 回答
0

如果你想通过去掉小数部分来舍入一个双数,你可以看到这个例子:

Long doubleToLong(double dAmount) {
    return (long) (int) dAmount;
}
于 2020-09-04T08:56:28.920 回答