1

I want manage numbers on a range from:

from 0,001 to 999,999

For representation reasons, I want to drop some of the accuracy keeping only the 3 most important digits of the number.

For the number 123,12 I expect the result 123.

For the number 12,123 I expect the result 12,1.

For the number 0,001 I expect the result 0,001.

The best solution I thought of is transforming the number into a String, and back again to double, this way:

 number = number*1000;
 String s = new String(number);
 s = s.substr(0, 3) + "000";
 number = Double.parseDouble(s);
 number = number/1000;

This does the job but it looks both poorly performing and not elegant. Any more clever alternative? Thank you!

Mr.Eddart
  • 10,050
  • 13
  • 49
  • 77
  • Use `String.format("%.3g",number)`. – DodgyCodeException Feb 19 '18 at 16:53
  • Possible duplicate of [Round a double to 3 significant figures](https://stackoverflow.com/questions/7548841/round-a-double-to-3-significant-figures) – Oneiros Feb 19 '18 at 17:04
  • Not a duplicate of "Round a double to 3 significant figures" because we don't want to create another `double` with 3 sig figs, which is what that other question was about. Here, we just want to *display* it with 3 sig figs. – Klitos Kyriacou Feb 19 '18 at 17:13
  • 1
    @KlitosKyriacou yet creating another double is exactly what the "current best solution" from the question does... – davmac Feb 19 '18 at 17:21
  • What exactly do you mean by "For representation reasons"? – Klitos Kyriacou Feb 19 '18 at 17:49
  • 1
    Please do not post duplicate questions. Also have you tried the obvious `x=floor(x*0.001)*1000.0` to round to `1000` or `x=floor(x*1000)*0.001` to round to `0.001` steps ... number of significant digits/scale/magnitude can be obtained by `log10` or from the exponent directly ... – Spektre Feb 19 '18 at 20:32
  • Not quite what you asked for, but consider switching to [fixed point arithmetic](https://en.wikipedia.org/wiki/Fixed-point_arithmetic). Dependant upon how often you need the conversion, this may be a more viable solution than messing around with doubles. –  Feb 19 '18 at 23:32
  • 1
    Possible duplicate of [How to round a number to n decimal places in Java](https://stackoverflow.com/questions/153724/how-to-round-a-number-to-n-decimal-places-in-java) –  Feb 19 '18 at 23:32
  • @davmac just because the OP probably used the wrong approach doesn't mean we have to do the same. Java doubles (IEEE floating point types in general) cannot represent numbers precisely to a given number of significant figures. The question is probably about representing them as text. If the OP really does want to represent a number numerically (rather than textually) to a certain number of sig figs, they should use BigDecimal instead. – Klitos Kyriacou Feb 20 '18 at 09:57
  • @KlitosKyriacou the fact that he converts back to double strongly suggests that's what the question is about, not just about "displaying" as you said. Sure, one option may be to use `BigDecimal` instead. – davmac Feb 20 '18 at 11:13
  • How is '0,001' the most significant 3 digits? – khriskooper Feb 20 '18 at 11:31

2 Answers2

1

Here's a somewhat-convoluted answer that doesn't require the use of any conversion to String:

final int numDigits = 3;

double d = 12.123;

int counter;        

for (counter = 0; counter < numDigits && d < Math.pow(10, numDigits - 1); counter++) {
    d *= 10;
}

d = Math.floor(d);

d /= Math.pow(10, counter);

System.out.println(d);

Output: 12.1

Essentially it multiplies the double by 10 until it reaches the largest value under 1000 (your maximum value is 999.999), keeping track of how many times it has been multiplied. It then performs the floor function to get rid of any precision to the right of the decimal point. Finally, we divide the number by 10, counter times, which provides us with the first 3 significant figures.

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • why not use `log10` to obtain number of digits instead of the looped `pow(10,?)` ? – Spektre Feb 20 '18 at 07:43
  • 1
    And yet this is not exact. For example, try changing 9.1234 to be 3 significant figures. You won't get 9.12, because you can't represent 9.12 as a double - the closest you can get to that is 9.11999999999999922. – Klitos Kyriacou Feb 20 '18 at 09:53
1

Perhaps use this RegEx to make the code more concise?

^[,0]{0,6}(\d{3}|\d{2},\d|\d,\d{2})
khriskooper
  • 767
  • 8
  • 18