24

Say we have a double value of 12345.6789 (should be dynamic)

Now the requirement is split the number and get the decimal digits and fractional digits, which would be:

double number = 12345.6789;
int decimal = 12345;
int fractional = 6789;

I get the decimal part work out but could you please give a hint on the fractional part? Thanks a lot.

Filburt
  • 17,626
  • 12
  • 64
  • 115
Dreamer
  • 7,333
  • 24
  • 99
  • 179
  • 1
    You need to decide if you're looking for the fractional part of the *printed* representation, or if you're willing to accept the seeming disparity in accuracy in the actual binary representation. – seh Jul 15 '12 at 21:03
  • @seh there is a difference that the fractional should only contain digits without the puncture. – Dreamer Jul 15 '12 at 21:14
  • The only way is to set the number of decimals to work with... Example with 2 decimals: 0.01 would be 1, and 0.10 would be 10. Look at my answer. – marcolopes Jun 24 '13 at 03:10
  • This is not an exact duplicate as here the fraction digits as int are asked. – R.Moeller May 03 '14 at 23:45

4 Answers4

44
double number = 12345.6789; // you have this
int decimal = (int) number; // you have 12345
double fractional = number - decimal // you have 0.6789

The problem here is that the fractional part is not written in memory as "0.6789", but may have certain "offsets", so to say. For example 0.6789 can be stored as 0.67889999291293929991.

I think your main concern here isn't getting the fractional part, but getting the fractional part with a certain precision.

If you'd like to get the exact values you assigned it to, you may want to consider this (altho, it's not a clean solution):

String doubleAsText = "12345.6789";
double number = Double.parseDouble(doubleAsText);
int decimal = Integer.parseInt(doubleAsText.split("\.")[0]);
int fractional = Integer.parseInt(doubleAsText.split("\.")[1]);

But, as I said, this is not the most efficient and cleanest solution.

ioreskovic
  • 5,531
  • 5
  • 39
  • 70
  • 5
    It needs a regex String argument for split method. So you need to use "\\." ref: http://stackoverflow.com/a/14833048/2000405 – Fatih Aksu Sep 03 '15 at 08:37
  • 1
    With your second solution for "exact values", if the fractional part starts with 0's, you will lose those 0's, ending up with a very different number. – Aldo Canepa Sep 10 '18 at 12:08
  • Work fine for `double` but does not work for `Double`. – attacomsian Jul 09 '19 at 23:10
10

You can't do what you want to do in an exact way.

One problem is if you have the number 1.05 what should the result be?

double number = 1.05;
int decimal = 1;
int fractional = 5; // Oops! "1.05" and "1.5" give the same result.

How about this?

int fractional = 05; // Still not correct. This is an octal number.

Another problem is that the double type can't exactly represent 12345.6789. It stores a slightly different number instead. This is called representation error. So the fractional part won't actually be 6789. Instead you can round it off to some number of decimal places.

int fractional = (int)Math.round((number - decimal) * 1000);
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • Won't really work all the time as the fractional part can have more then 4 digits :) – GETah Jul 15 '12 at 21:03
  • @Mark Byers thank you for the solution, but what about the fraction part is dynamic so we don't know how long it is so the *1000 solution may not be working. If the double is 12345.678 then it becomes *100. – Dreamer Jul 15 '12 at 21:18
  • 3
    @Subarule: I didn't give you a solution, I gave you an explanation of why it can't be done without changing the requirements. Which requirement are you willing to change? – Mark Byers Jul 15 '12 at 21:23
  • @Mark Byers May be convert to String and process and get back could be a solution? – Dreamer Jul 15 '12 at 21:26
3

You must decide how many decimals to support. I use this method:

int decimals = 2;
BigDecimal value = new BigDecimal(123.45).setScale(decimals, RoundingMode.HALF_EVEN);
BigInteger INTEGER = value.abs().toBigInteger();
//(value - INTEGER) * (10 ^ decimais)
BigInteger DECIMAL = ((value.subtract(new BigDecimal(INTEGER))).multiply(new BigDecimal(10).pow(decimals))).toBigInteger();
marcolopes
  • 9,232
  • 14
  • 54
  • 65
1

You can convert to String, find the decimal point, get the substring and then convert back to Integer.

String numberStr = Double.toString(number);
String fractionalStr = numberStr.substring(numberStr.indexOf('.')+1);
int fractional = Integer.valueOf(fractionalStr); 
Behzad Momahed Heravi
  • 1,383
  • 1
  • 12
  • 17