在没有 Round Java 的情况下从 double 转换为 long

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18110757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:27:39  来源:igfitidea点击:

Convert from double to long without Round Java

javadoublelong-integer

提问by user2661808

I'm trying to convert a random double to a long without rounding or truncating it. First I change the double to a string, to know how many decimal places there are and then I change the value to long. My problem is that the number of the last decimal place is not always correct and I don't know the reason and how I can change it. Here is the code:

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

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

And that's the output:

这就是输出:

d: 19.625014811604743

电话:19.625014811604743

double converted to long: 19625014811604744

double 转换为 long:19625014811604744

d: 9.143326452202839

d: 9.143326452202839

double converted to long: 9143326452202838

double 转换为 long:9143326452202838

d: 5.8964228376511105

d:5.8964228376511105

double converted to long: 58964228376511104

double 转换为 long:58964228376511104

d: 15.045936360299917

d: 15.045936360299917

double converted to long: 15045936360299918

double 转换为 long:15045936360299918

d: 14.147950026532694

d: 14.147950026532694

double converted to long: 14147950026532694

double 转换为 long:14147950026532694

回答by Andrei Juan

If your goal is to obtain a random long number, then I would strongly recommend using Random.nextLong() instead.

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

回答by gr3co

Editing your current implementation:

编辑您当前的实现:

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

Or if you just want a random LongI would recommend using Random.nextLong()instead.

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

回答by Grammin

test=(long) (Math.pow(10, s.length()-s.indexOf(".")-1)*z);

Is messing up your double in the arithmetic, try something like this:

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

public long convertDoubleToLong(double d){
  String str = Double.toString(d);
  return Long.parseLong(str.replace(".", ""));
}

回答by J.P. Armstrong

You can do something like this...

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

double x = 19.625014811604743;
while(x % 1 != 0) x *= 10;
long y = (long) x;
System.out.println("x: "+ x + " y: "+ y);

回答by yshavit

The other answers have pointed out how you can fix this, but your other question was whyit happens. The answer to that is floating-point error.

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

Floating-point numbers consist of three main parts: a sign (+ or -), a mantissa and an exponent. Essentially, the number is represented as essentially (sign) (mantissa) * 2^(exponent)(but not exactly -- see links below). As you can imagine, not all numbers fit snugly into this representation; some have to be approximated. The quintessential example is one-tenth, which in binary has an infinite repeating sequence and so has to be approximated in doubles.

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

At high values -- those greater than the mantissa can represnt -- there are some integers that can't be represented exactly. This happens at 2^53; any number greater than this has to be approximated, and the numbers you mention are such examples.

在高值时——那些大于尾数可以表示的值——有一些整数无法准确表示。这发生在 2^53;任何大于这个的数字都必须近似,你提到的数字就是这样的例子。

You don't even need Math.powto demonstrate this; literals will do just fine.

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

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

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

This will print:

这将打印:

19.625014811604743
1.9625014811604744E16

Notice the 4 at the end of that second value. 19625014811604744 is the closest number to 19625014811604743 that can be represented as a double.

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

Related reading:

相关阅读: