2017-06-05 134 views
1

我想找到一种有效的方法来确保 double中的小数位数不超过3。查找double值的小数位数的有效方法

double num1 = 10.012; //True 
double num2 = 10.2211; //False 
double num2 = 10.2; //True 

目前,我所做的只是使用正则表达式分割和计数索引。如下所示。

String[] split = new Double(num).toString().split("\\.") 
split[0].length() //num of decimal places 

是否有一个有效的或更好的方式来做到这一点,因为我会调用这个函数 了很多?

+0

我觉得你是因为麻烦在这里,因为double不是一个确切的表示,2.112可以结束2.119999999。你不是更好使用BigDouble吗? – vikingsteve

+1

在这里做一个重要的区别:一个'double'完全可以包含一个值,该数值*数学上*在(比方说)第十万个地方有一个(比方说)非零值,但当转换为字符串时* 将不会。这就是IEEE-754双精度二进制浮点的喜悦。从字符串表示中获得的数字的数量只有为区分该值与其相邻的可表示值所需的数量。 –

+0

@vikingsteve这就是我所倾向的,但我主要关心的是记忆。就像内存效率如何达到BidDouble一样 –

回答

2

如果你想要一种解决方案,以一种将double转换为字符串的最终结果的方式告诉你这些信息,那么效率就不会真正进入它;你基本上必须转换为字符串并检查。结果是,double是完全可能的,它包含一个在数学上有一个(比方说)非零值(例如)在千分之一的位置的值,但是当它被转换为字符串时不会。这就是IEEE-754双精度二进制浮点的乐趣:从字符串表示中获得的数字的数量仅为区分该值与其相邻可表示值所需的数量。从the Double docs

多少位必须打印为一个小数部分?必须至少有一位数字来表示小数部分,并且除此之外还必须包含尽可能多的数字,但数量必须与唯一地区分参数值与类型为double的相邻值所需的位数相同。也就是说,假设x是由该方法对有限非零参数产生的十进制表示法所表示的确切数学值d。然后d必须是最接近xdouble值;或者如果两个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,请根据您的数值范围选择精度并使用intlong。例如,如果您只需要一分钱的精确度,那么您会使用乘以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 
+0

它应该是相反的吗?如果我使用长乘以10000乘数50.0411 500411. 500411%10000给出411.我怎么知道它是超过3 d.p.?你能解释一下吗?在此先感谢您的帮助应该是我的 –

+0

@KalebBlue:对不起,我不清楚。 'value%10000> 0'表示它在*有效。我已经澄清并在上面进行了扩展。 :-) **和**它应该是'!=',因为你可以有负值,'-102211000%10000'是'-1000',而不是'1000'。对于那个很抱歉。 –

相关问题