在没有 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
Convert from double to long without Round Java
提问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 Long
I 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.pow
to 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:
相关阅读:
- http://floating-point-gui.de/Good introduction
- http://en.wikipedia.org/wiki/Binary64A bit more detail, about doubles specifically
- http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlA bit dense, but important once you get the hang of things
- http://en.wikipedia.org/wiki/Floating_point