如果你想要一种解决方案,以一种将double
转换为字符串的最终结果的方式告诉你这些信息,那么效率就不会真正进入它;你基本上必须转换为字符串并检查。结果是,double是完全可能的,它包含一个在数学上有一个(比方说)非零值(例如)在千分之一的位置的值,但是当它被转换为字符串时不会。这就是IEEE-754双精度二进制浮点的乐趣:从字符串表示中获得的数字的数量仅为区分该值与其相邻可表示值所需的数量。从the Double
docs:
多少位必须打印为米或一个小数部分?必须至少有一位数字来表示小数部分,并且除此之外还必须包含尽可能多的数字,但数量必须与唯一地区分参数值与类型为double
的相邻值所需的位数相同。也就是说,假设x是由该方法对有限非零参数产生的十进制表示法所表示的确切数学值d。然后d必须是最接近x的double
值;或者如果两个double
值同样接近X,然后d必须是其中之一,并d的有效数必须0
的至少显著位。
但是,如果你不担心这一点,假设限制你的数值范围,以long
是好的,你可以做这样的事情:
private static boolean onlyThreePlaces(double v) {
double d = (double)((long)(v * 1000))/1000;
return d == v;
}
...这应该有较少的内存开销而不是一个String
- 旅行。
然而,我想如果有一个不公平的次数时方法和Double.toString(double)
结果在数字方面没有匹配到小数点后,由于上述原因,很惊讶。
在关于这个问题的评论,你说(当我问起值范围):
老实说,我不知道。我正在处理价格;对于初学者,我假设0-200K
使用double
对于金融价值通常不是一个好主意。如果由于内存问题而不想使用BigDecimal
,请根据您的数值范围选择精度并使用int
或long
。例如,如果您只需要一分钱的精确度,那么您会使用乘以100的值(例如,2000是Ⓠ20[或您使用的任何币种,我使用Ⓠ代表quatloos])。如果你需要一分钱的精确度(如你的问题所示),然后乘以100000(例如,2000000是Ⓠ20)。如果您需要更高的精度,请选择更大的乘数。即使你去百分之一便士(muliplier:10000000),与long
你有一个范围从-1922,337,203,685到-1922,337,203,685。
这有一个副作用,它使这个检查更容易:只是一个直的%
。如果您的乘数为10000000(一分钱的千分之一),则只需value % 10000 != 0
即可识别无效数字(或value % 10000 == 0
以识别有效数字)。
long num1 = 100120000; // 10.012 => true
// 100120000 % 10000 is 0 = valid
long num2 = 102211000; // 10.2211 => false
// 102211000 % 10000 is 1000 = invalid
long num3 = 102000000; // 10.2 => true
// 102000000 % 10000 is 0 = valid
我觉得你是因为麻烦在这里,因为double不是一个确切的表示,2.112可以结束2.119999999。你不是更好使用BigDouble吗? – vikingsteve
在这里做一个重要的区别:一个'double'完全可以包含一个值,该数值*数学上*在(比方说)第十万个地方有一个(比方说)非零值,但当转换为字符串时* 将不会。这就是IEEE-754双精度二进制浮点的喜悦。从字符串表示中获得的数字的数量只有为区分该值与其相邻的可表示值所需的数量。 –
@vikingsteve这就是我所倾向的,但我主要关心的是记忆。就像内存效率如何达到BidDouble一样 –