Counting decimal places

Hi

I've written the following code to try to count how many decimal places there are in a floating point number:
1
2
3
4
5
6
7
8
9
10
  double d_dec = 342.3781898;
  double epsilon = 0.0000001;
  int count = 0;
  while ((d_dec * 10.0) - floor(d_dec) * 10.0 > epsilon)
  {
      cout << count << " "<< setprecision (13)<<d_dec * 10.0 << " - " << floor(d_dec * 10.0) << " = " << (d_dec * 10.0) - floor(d_dec * 10.0) << endl;
      
      d_dec*= 10.0;
      count++;
  }


However, it doesn't appear to work as it outputs this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0 3423.781898 - 3423 = 0.7818979999997
1 34237.81898 - 34237 = 0.8189799999964
2 342378.1898 - 342378 = 0.1897999999346
3 3423781.898 - 3423781 = 0.8979999991134
4 34237818.98 - 34237818 = 0.9799999892712
5 342378189.8 - 342378189 = 0.7999998927116
6 3423781898 - 3423781897 = 0.9999990463257 //this is where it goes wrong - why is the first and second number different?
7 34237818980 - 34237818979 = 0.9999923706055
8 342378189800 - 342378189799 = 0.9999389648438
9 3423781898000 - 3423781897999 = 0.99951171875
10 3.423781898e+13 - 3.423781898e+13 = 0.99609375
11 3.423781898e+14 - 3.423781898e+14 = 0.9375
12 3.423781898e+15 - 3.423781898e+15 = 0.5
13 3.423781898e+16 - 3.423781898e+16 = 0
14


I assume that this occurs because d_dec is not exactly 3423781898 (i.e. its a minuscule amount less so it rounds it down). Does anyone know to solve this problem? I've tried a few things (e.g. using round()) but nothing seems to work.

Thanks
floating point cannot exactly represent all possible values. in the commented values, the answer is 1. The result is 0.999999 something. The answer is effectively 1. Its correct, within the machine's ability to handle the values. You are up against the limits of what a double can handle. You can use something with more bits, but everything has limits and eventually you will hit them.


ok, can you recommend another approach to how I can count the number of decimal places in a digit?
Did some quick testing. Seems best results if you feed in a double in the [0,1] range -- that is, strip the integer part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

using namespace std;

// For best results, feed in double without any integral part
//   d in range 0..1
int DigitsAfterDecimal(double d)
{
    ostringstream oss;
    oss << setprecision(12);
    oss << d;
    return oss.str().size()-2;
}

int main() 
{
    double d_dec = 342.3781898;
    d_dec -= (int)d_dec;
    cout << setprecision(12);
    cout << d_dec << endl << DigitsAfterDecimal(d_dec) << endl;
    
    return 0;
}

Can test at https://repl.it/repls/LoudHarshAggregator

0.3781898
7
thanks but I'm trying to implement it from scratch
rozick1 wrote:
thanks but I'm trying to implement it from scratch

lol, what does that even mean? I did write it from scratch... it's not like I called std::DigitsAfterDecimal()

rozick1 wrote:
6 3423781898 - 3423781897 = 0.9999990463257 //this is where it goes wrong - why is the first and second number different?

I think back when your count was 0, just multiplying by 10 already negatively affected the result
Last edited on
well, i'm trying to write a function which converts floats to strings...which is what stringstream does
Topic archived. No new replies allowed.