Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine number of non-zero digits right of decimal point

Tags:

c++

I would like compute the number of non-zero and non-repeating (ie. 1.999999999) to the right of the decimal point. Eg:

x.xx = 2
x.xxx = 3
x.xxx000 = 3

I can do this by converting the number to a string but I was wondering if there is a faster way using math. Any ideas?

Thanks.

EDIT: Many people seem to think this is a fools errand because of the way numbers are represented in computers. However, allow me to explain the context of the problem. Suppose you are to write a method to randomly generate a floating point number. The number you generate must have a certain precision, therefore you must round the randomly generated number to the specified precision. For example if the precision is 2, your random number cannot be 0.012, it must be rounded to 0.01. The problem is you are not provided the precision, instead you are given the increment, which in the aforementioned case would be 0.01. Given 0.01 or 0.002 or any other such increment which is less than 1, you must find the precision.

Edit: Removed my incorrect usage of the term significant digits.


2 Answers

The number of significant digits is not something you compute by looking at the number. You compute it based on the number of significant digits in the other numbers you used to compute the number you're looking at, or by the precision of the instrument used to carry out your measurement.

Insignificant digits are neither displayed nor used, so the fact that your number x.xxx000 has six digits to the right of the decimal point means that all six of those digits are significant. The number 2.3 is not the same as the number 2.300.

The issue of whether to count zeros as significant comes into play when you have a number like 2300, where the number is an integer multiple of 10. Are there two significant figures, or four? Write it in scientific notation to be sure: 2.3 × 103 or 2.300 × 103.

The native numeric types of most languages, including C++, do not handle this notion of significant digits. In general, they don't even handle digits at all; they handle bits. If your implementation's float type is 32 bits, then all 32 of those bits are treated as significant all the time.

like image 177
Rob Kennedy Avatar answered Sep 05 '25 05:09

Rob Kennedy


One technique would be to multiply the number by 10 until the digit in the ones place is 0 (which you could discern using %):

float x = /*...*/;
int   count = 0;

while (true)
{
    x *= 10;

    if (static_cast<long>(x) % 10 == 0)
        break;

    ++count;
}

// at this point count has the number of digits after the decimal point.

Here's my beef with what I wrote:

  • It could never terminate (theoretically).
  • There is a lot of multiplying and modulus going on in the above algorithm so it is quite expensive.
  • Every iteration increases the chances of hitting floating-point rounding errors.
  • This will fail for x.x0x where x represents any number of digits. (thanks Daniel Brückner)

In short, then, I'd lean towards seralization-and-searching.

like image 21
fbrereto Avatar answered Sep 05 '25 05:09

fbrereto