2016-07-15 95 views
1

我想截断Java中的浮点数,直到两个第一个非零十进制数字。例如,0.0001340.0001311.0040111.0040将浮点数截断为两个第一个非零十进制数字

我能想到的唯一解决方案是去掉整数部分,然后乘以10,直到得到一个大于或等于10的数字。然后将原始浮点数截至number of multiplications十进制数字。

但我可能不得不经常这样做,所以我正在寻找更快的解决方案。

我的测试代码:

public static String truncateTo2NonZero(double f) { 
    int integral = (int)f; 
    double decimal = f - integral; 
    int digits = 0; 

    while (decimal < 10) { 
     decimal *= 10; 
     digits++; 
    } 

    double ret = (int)decimal/Math.pow(10, digits); 
    ret += integral; 

    return Double.toString(ret); 
} 

public static void main(String args[]) { 
    final int TESTS = 1000000; 
    double[] floats = new double[TESTS]; 

    Random random = new Random(); 
    for (int i = 0; i < TESTS; ++i) { 
     int zeros = random.nextInt(6) + 3; // divide by 10^zeros 
     double digits = random.nextInt(100) + 100; // 3 last digits 
     floats[i] = digits/Math.pow(10,zeros) + random.nextInt(20) + 1; 
    } 

    long startTime = System.nanoTime(); 
    for (int i = 0; i < TESTS; ++i) 
     truncateTo2NonZero(floats[i]); 
    long endTime = System.nanoTime(); 

    long duration = endTime - startTime; 
    System.out.println(duration/1000000); // in milliseconds 
} 

我使用Windows 7家庭高级版64位。的java -version输出:

java version "1.8.0_20" 
Java(TM) SE Runtime Environment (build 1.8.0_20-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) 
+3

这看起来不像那些笨蛋。这里的OP想要有一个动态的小数位数,即保留最多两个第一个非零的十进制数字。 – Tunaki

+0

@copeg不重复。这就像Tunaki说的。我认为从我给出的两个例子中可以清楚地看出。 – devil0150

+1

“浮点”“十进制数字”这两个短语不应出现在同一句子中。你应该使用'BigDecimal'。 –

回答

1

当你说你要“截断”这听起来像是一种显示格式。这就是说浮游物对此不友善。 BigDecimals是。这应该给你一个开始,当然需要错误检查。

static String roundToLastTwoDecimalDigits(float f) { 
    // split whole number and decimals 
    String[] floatParts = new BigDecimal(f).toPlainString().split("\\."); 

    int wholeNumberPortion = Integer.parseInt(floatParts[0]); 

    // count zeroes 
    String decimalPortion = floatParts[1]; 
    int numDecimalPlaces = 0; 
    while (decimalPortion.charAt(numDecimalPlaces) == '0') 
     numDecimalPlaces++; 

    // get 3 digits to round 
    String toRound = decimalPortion.substring(numDecimalPlaces, 
      numDecimalPlaces + 3); 

    int decimalForRounding = Math.round(Float.parseFloat(toRound)/10); 

    StringBuilder sb = new StringBuilder(); 

    sb.append(wholeNumberPortion); 
    sb.append("."); 
    for (int i = 0; i < numDecimalPlaces; i++) 
     sb.append("0"); 
    sb.append(decimalForRounding); 

    return sb.toString(); 
} 
+0

刚刚测试过,而且速度较慢。 3703毫秒,而我的方式为538毫秒,500k随机浮动。 – devil0150

+1

@ devil0150'BigDecimal'并不意味着要快,它的意思是正确的。 –

+0

@ devil0150你能分享你的代码吗?我正在考虑一种算法,就像Compass的算法一样,但计算量较小。为了确保我们将苹果与苹果进行比较,请分享您的代码,将您产生随机数的时间和方法分解出来。另外,让我们知道您的机器/ JVM规格。 – mohsenmadi

相关问题