我想将一些双精度值格式化为忽略起始零的特定位数。
例如,假设格式为 6 位:
131.468627436358 -> 131.469
3.16227766016838 -> 3.16228
0.66018099039325 -> 0.660181
0.02236067977499 -> 0.0223607
BigDecimal 允许正确处理有效数字。这个:
MathContext round3SigFig = new MathContext(3,RoundingMode.HALF_UP);
System.out.println((new BigDecimal(0.000923874932)).round(round3SigFig));
产生:
0.000924
但是,显然,通过任意精度对象表示传递浮点并不理想。
使用对数函数计算您需要的附加位数。
public static int leadingZeros (double d) {
return (d >= 1.0) ? 0 : (int) (-1 * (Math.floor (Math.log (d) / Math.log (10))));
}
为了
System.out.println (leadingZeros (4));
System.out.println (leadingZeros (0.4));
System.out.println (leadingZeros (0.04));
System.out.println (leadingZeros (0.004));
它返回 0、1、2、3。
将此视为最后的机会选项:如何将数字转换为字符串,记住前六位数字并带有“,”并转换回双精度数。
我相信这与以下问题密切相关:使用最多五个总数字格式化双精度值,如有必要,四舍五入十进制数字
我链接到哪些用途的问题中有一个答案,MathContext
并且BigDecimal
(比如也许WeCouldStealAVan的答案)。但是,这对我来说不太奏效,因为我关心数字的总数。但是,它可能对您有用。
我最终编写了自己的自定义解决方案,其格式完全符合我的需要。也许这也满足您的要求,或者可以轻松修改以满足它们:
public static String format( double value, int totalDigits )
{
String s = String.valueOf( value );
int decimal = s.indexOf( '.' );
// there is no decimal part, so simply return the String
if ( decimal == -1 )
{
return s;
}
else
{
int finalLength;
// example: 23.34324
// the final result will be length totalDigits + 1 because we will include the decimal
if ( decimal < totalDigits )
{
finalLength = totalDigits + 1;
}
// example: 99999
// the final result will be length totalDigits because there will be no decimal
else if ( decimal == totalDigits )
{
finalLength = totalDigits;
}
// example: 999999.999
// we can't make the final length totalDigits because the integer portion is too large
else
{
finalLength = decimal;
}
finalLength = Math.min( s.length( ), finalLength );
return s.substring( 0, finalLength );
}
}
public static void main( String[] args )
{
double[] data = { 1, 100, 1000, 10000, 100000, 99999, 99999.99, 9999.99, 999.99, 23.34324, 0.111111 };
for ( double d : data )
{
System.out.printf( "Input: %10s \tOutput: %10s\n", Double.toString( d ), format( d, 5 ) );
}
}