12

I have a double variable d = 1.15.

I want the number after the decimal point, i.e. "15".

What is best way to achieve this in Java?

I have tried like this:

Double d = 1.15;
String str = d.toString();
int len = str.substring(str.indexOf(".")).length() - 1;
int i= (int) (d * (long)Math.pow(10,len) % (long)Math.pow(10,len));

But I didn't get the proper answer because when I convert d.toString() the answer is 14.999999999999986.

halfer
  • 19,824
  • 17
  • 99
  • 186
user1023675
  • 289
  • 1
  • 4
  • 13
  • http://stackoverflow.com/questions/5017072/how-to-get-the-decimal-part-of-a-float – John Eipe Jan 17 '12 at 06:24
  • 1
    This question has been informative for me - I've learned how many people don't actually run the code they post, or really read the question. The question is how to get `15` from `1.15`. Only Arjun's nailed it so far, because he saw this problem for what it really is: a String parsing question. Just because the poster tried using math doesn't mean the answer has to follow the same path. – Paul Jan 17 '12 at 06:52
  • @Paul - I'd say that the OP's last (negative) example gives the lie to that theory. If this was simply a string parsing problem, then the OP would be happy with "999999999986" as the answer ... – Stephen C Jan 17 '12 at 07:07
  • 1
    @StephenC, where did you get that from? He said he wants `15` as the answer (2nd line of his post) and his code was giving him `14.9999...`. Change the question from numbers to text and it's still the same problem: given a string `abc.def`, how does he extract just `def`? – Paul Jan 17 '12 at 07:12
  • @Paul - I don't know where you get that it is only a string problem. That all depends on where he got his double value from and which value it is. Depending on that the `valueOf` or the `toString` will not produce the expected result. And the precision issues are only one part of that. The other is the scientific notation that `valueOf`/`toString` will give you. – Turismo Jan 17 '12 at 08:23
  • IMHO, Don't use `Double` when you mean to use `double`. – Peter Lawrey Jan 17 '12 at 13:29
  • 1
    A problem with your solution is that `0.1` `0.01` and `0.000001` will all result in `1`. – Peter Lawrey Jan 17 '12 at 13:30
  • @Turismo http://xkcd.com/974/ – Paul Jan 17 '12 at 13:34

15 Answers15

14

Try this:

String numberD = String.valueOf(d);
numberD = numberD.substring(numberD.indexOf("."));

Now this numberD variable will have value of 15

Elikill58
  • 4,050
  • 24
  • 23
  • 45
Lucifer
  • 29,392
  • 25
  • 90
  • 143
  • 1
    +1, it's simple and the answer doesn't have to be mathematical. Treating it as a `String` problem removes the issues with precision. Nice job. – Paul Jan 17 '12 at 06:36
  • This is incorrect. You'll get decimal as well as part of the result. Not sure why was it upvoted by readers without even trying. Peter's answer is correct. You need another .substring(1) at the end. – rajneesh2k10 Jun 09 '16 at 16:04
  • no it will not, it will return the value of `.24`. Modify `numberD.indexOf('.') + 1` to get `24`. – Hendra Anggrian May 08 '17 at 16:11
  • There are certain countries where `,` are used instead of `.`. One should be warned about this before using that technique. – Augusto Carmo Jul 23 '19 at 13:38
11

Try Math.floor();

double d = 4.24;
System.out.println( d - Math.floor( d )); 

To prevent rounding errors you could convert them to BigDecimal

    double d = 4.24;
    BigDecimal bd = new BigDecimal( d - Math.floor( d ));
    bd = bd.setScale(4,RoundingMode.HALF_DOWN);
    System.out.println( bd.toString() );

Prints 0.2400

Note that the 4 in setScale is the number of digits after the decimal separator ('.')

To have the remainder as an integer value you could modify this to

BigDecimal bd = new BigDecimal(( d - Math.floor( d )) * 100 );
bd = bd.setScale(4,RoundingMode.HALF_DOWN);
System.out.println( bd.intValue() );

Prints 24

stacker
  • 68,052
  • 28
  • 140
  • 210
  • 1
    I ran your code and got `0.2400000000000002` - I don't think he'll find that helpful. All that rep and you can't test your code? :D – Paul Jan 17 '12 at 06:34
  • @Paul Thanks fixed it, it's an IEEE 754 representation he just needs to round the value. – stacker Jan 17 '12 at 06:46
  • @PeterLawrey, sure, I've heard of those. Tell me how this is related to the poster's desire to get just the part after the decimal point, i.e. `24` for stacker's example. – Paul Jan 17 '12 at 06:47
  • @stacker, how do you round `0.2400000000000002` to `24`? – Paul Jan 17 '12 at 06:48
  • @Paul the requirements were not clear to me, I added an example of rounding to .24 and another of 24. I hope it's clear now. – stacker Jan 17 '12 at 06:54
  • @Paul See my answer on how to round the result. – Peter Lawrey Jan 17 '12 at 13:28
  • intValue() fun does nto exist ?? only intValueExact() which crashes – Jono Jul 23 '20 at 11:36
5

Try out RegEx, here ^\d*\., will search for digits followed by dot and replace with blank.

for(double d : new double[]{1.15,0.009,222.9,3.67434}){
    System.out.println(String.valueOf(d).replaceAll("^\\d*\\.",""));
}

gives:

15
009
9
67434
5

The number after the decimal point is not a well defined concept. For example for "4.24", it could be "0.24", "0.239999999999" (or similar), "24" or "239999999999".

You need to be clear if you are talking about a number or a string of decimal digits ... and whether the input value is a representation of a binary floating point number (in which case "4.24" is most likely an approximation) a decimal floating point number.

Depending on your interpretation, the correct answer will be different.


But i didn't get the proper answer because when I converted d.toString() the answer is 14.999999999999986.

You are running up against the problem that double and float are base-2 floating point formats, and in most cases they CANNOT represent decimal floating point numbers precisely. There is no fix for this ... apart from using something like BigDecimal to represent your numbers. (And even then, some loss of precision is possible whenever you do a division or modulo operation.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

If your double is:

d = 1.25;

And if you do this:

String number = String.valueOf(d);

number = number.substring(number.indexOf(".")).substring(1);

then number will be 25.

I don't know if this is the best way to do this, but it works.

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Peter
  • 21
  • 4
2

If you want the decimal places and you want to round the result.

double d = 4.24;
System.out.printf("%0.2f%n", d - (long) d);

prints

0.24

If you want a rounded value, you have to determine what precision you want.

double d = 4.24;
double fract = d - (long) d;
fract = (long) (fract * 1e9 + 0.5) / 1e9; // round to the 9 decimal places.
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0
    double d = 4.24;
    d = (d - Math.floor( d ));
    int e = (int)(Math.round(d*100));
    System.out.println(e);

Yields 24

0
  Scanner scr= new Scanner (System.in);
  double d= scr.nextDouble();

  BigDecimal bc= new BigDecimal ((d - Math.floor(d))*1e5); 

  bc=bc.setScale(4,RoundingMode.HALF_DOWN); 

  double f = bc.doubleValue();

    while(f%10==0)
    {
      f=f/10;
    }
  System.out.println(f);
  • This is the simplest way to solve the problem. Pls upvote and share. If you cannot understand the problem, pls feel free to ask me. – Pravaal Reddy Aug 10 '21 at 04:22
0

Just as in any other language: multiply by 10 and check the int part of remnant when dividing by 10. The same way you would extract digits from an integer.


short[] digits = new short[max_len];
double tmp = d - ((int) d);
for (int i = 0; i < digits.length && tmp != 0; i++)
{
  tmp *= 10;
  digit[i] = (short) tmp;
  tmp -= (int) tmp;
}

But be aware that for double you need to introduce a precision limit - the maximum number of digits to extract (max_len from the code sample above).

Slight update (added rounding at the edge of precision):

double d = 1.15;
        short[] digits = new short[10];
        double tmp = d - ((int) d) + 0.5 * 1e-10;
        for (int i = 0; i < digits.length && tmp != 0; i++)
        {
            tmp *= 10;
            digits[i] = (short) tmp;
            tmp -= (int) tmp;
        }
Andrei LED
  • 2,560
  • 17
  • 21
  • -1 Wow, not only does your code not work, this is way too complex for the question. I ran your code and the array contained 1 and 4, for an input value of 1.15. – Paul Jan 17 '12 at 06:41
  • Actually the result is 1 4 9 9 9 9 9 9 9 9 ... That's the way it's with doubles - you can't precisely say how much digits it has after the dot because of inaccuracy of their arithmetics. And if you got that double from some expression (not by explicitly defining its value) be sure it has inaccuracy in it. That's why I told about precision limit. Stephen C gave a good explanation for it above. – Andrei LED Jan 17 '12 at 07:39
  • I ran your code and got an array of 2 that contained a 1 and a 4. I set `max_len` to 2 since he wanted a 2 character response: `15`. He's not trying to do math - he just wants text out. – Paul Jan 17 '12 at 07:42
  • If you have a double and want to get its part after the dot you wouldn't know how much digits there're before you try to extract them. I ran my code with max_len=10. AS for not doing math: printing a double causes some kind of conversion into a decimal representation. As user1023675 mentioned conversion to String returns 14.999999999999986 in his case. – Andrei LED Jan 17 '12 at 07:54
  • If the solution with parsing a string works for user1023675 let's just finish this discussion - I see no point in it. – Andrei LED Jan 17 '12 at 07:57
  • You don't need to know how many digits come after the decimal - see Arjun's answer. If you have a demonstration where converting `double` to `String` leads to rounding errors please share it. The poster's problem came about because of the math, not the conversion to `String`. – Paul Jan 17 '12 at 07:57
  • double d = 1.0 / 3; Arjun's code would give me answer '3333333333333333'. But there're infinitely more digits after the dot. Java here implicitly chose precision point for me. What answer here should be considered correct? See a slight update to my code above - I added rounding at the max_len digit. – Andrei LED Jan 17 '12 at 08:33
0

Have you tried d = d%1.0? That should return the remainder of dividing d by 1, which should just be the decimal portion.

You could also do this to get the value as an int: d = (int)((d%1.0)*100)

aoi222
  • 723
  • 1
  • 5
  • 11
  • 2
    I wasn't sure it did at first either, but after reading this I'm pretty sure it does, unless I read it wrong. http://stackoverflow.com/questions/2947044/how-do-i-use-modulus-for-float-double – aoi222 Jan 17 '12 at 06:25
  • Wow, that's really an interesting feature. Good now I know about this. Thanks. – Shamim Hafiz - MSFT Jan 17 '12 at 06:26
  • To me it's just as clear as anything else, though maybe that's because I'm more used to this style. Though it never hurts to add comments to explain a line such as this. – aoi222 Jan 17 '12 at 06:35
  • -1 I ran your first bit like so: `double d = 1.15; d = d % 1.0; System.out.println("d=" + d);` and the output was `d=0.1499999999999999`. I ran your 2nd bit of code and got `d=14.0`, neither of which is close to the `15` he was looking for. – Paul Jan 17 '12 at 06:46
0

Instead of d.toString(), try this:

String str = String.format("%.2f", d);
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
-1

try this :

double d = 1.1512;

int i = (int) (d*100 - Math.floor(d)*100);

now this will give you : 15

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
-1
    ExAMPLE :

    Double d = 469.951479;

    String string = d.toString();

    char[] len = string.substring(string.indexOf(".")).toCharArray();

    System.out.println(len);
-1
double myNumber = 1.15;
//numbers After Dot
double n = 2;
double right_of_dot = (myNumber - (int) myNumber)*Math.pow(10,n);
  • 1
    When converting d.toString() the answer is still 14.999999999999991, the same improper result as before. – karel Apr 05 '20 at 05:36
-3

Try this:

var decimalsOnly = (parseFloat(decNum)-parseInt(decNum,10)).toFoxed(2);
Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
  • 3
    1. This looks more like JavaScript. 2. `toFoxed` seems to be a typo of `toFixed` which is [not available in Java](https://stackoverflow.com/questions/10631813/javascript-tofixed-equivalent-in-java) though – Nowhere Man Oct 08 '20 at 13:47