C/C++ Counting the Number of Decimals

C/C++ counting the number of decimals?

Two ways I know of, neither very clever unfortunately but this is more a limitation of the environment rather than me :-)

The first is to sprintf the number to a big buffer with a "%.50f" format string, strip off the trailing zeros then count the characters after the decimal point. This will be limited by the printf family itself. Or you could use the string as input by the user (rather than sprintfing a floating point value), so as to avoid floating point problems altogether.

The second is to subtract the integer portion then iteratively multiply by 10 and again subtract the integer portion until you get zero. This is limited by the limits of computer representation of floating point numbers - at each stage you may get the problem of a number that cannot be represented exactly (so .2155 may actually be .215499999998). Something like the following (untested, except in my head, which is about on par with a COMX-35):

count = 0
num = abs(num)
num = num - int(num)
while num != 0:
num = num * 10
count = count + 1
num = num - int(num)

If you know the sort of numbers you'll get (e.g., they'll all be 0 to 4 digits after the decimal point), you can use standard floating point "tricks" to do it properly. For example, instead of:

while num != 0:

use

while abs(num) >= 0.0000001:

Getting the amount of decimals a number has in c?

If you don't care about rounding then you don't need to count the number of decimal places, you can just count the number of binary places. This is because 10 contains 2 as a factor exactly once so 10^n and 2^n have the same number of 2s as factors. The fastest way to count the number of binary places is to get the exponent of the floating point number.

e.g. binary 0.001 takes 3 decimal places to represent 0.125, 0.0001 takes 4 0.0625.

You can either get the fractional part of the value and keep multiplying by 2 and removing the integer as people have suggested doing with 10 (it will give you the same answer).

Or you can have a bit more fun over optimising the solution (the places function does most of the work):

#include <math.h>

int saturateLeft (unsigned int n) {
n |= (n << 1);
n |= (n << 2);
n |= (n << 4);
n |= (n << 8);
n |= (n << 16);
return n;
}

int NumberOfSetBits(int i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

int places (double num) {
int exponent;
float mantissa = frexp (num, &exponent);

/* The answer we are looking for is given by the
(number of bits used by mantissa) - the exponent.
*/

unsigned intMantissa = scalbnf (mantissa, 32);
/* Could also be got by doing:
intMantissa = *(unsigned *)&mantissa << 9;
*/

/* To work out how many bits the mantissa covered we
need no gaps in the mantissa, this removes any gaps.
*/

intMantissa = saturateLeft (intMantissa);
int bitCount = NumberOfSetBits (intMantissa);

/* bitCount could also be found like this:
intMantissa = ~intMantissa;
int bitCount = 32 - ilogb (intMantissa) - 1;
*/

int result = bitCount - exponent;
if (result < 0)
return 0;

return result;
}

The bitCounting algorithm was found here.

How to count the number of digits in double/float C++

Floating point numbers in computer use binary (base 2, zeros and ones, like almost all numbers in computers). So there is an exact number of binary digits in them, more in double and less in float. However, if you convert a decimal constant like 3.141592 to double, then print it with full accuracy, you don't get same number back. This is because converting the decimals between bases isn't exact in general (it's similar effect effect you get with 1/3 having infinite decimal expansion 0.33...). Example:

double pi = 3.141592;
std::cout << std::setprecision(100) << pi << std::endl;

Outputs for me:

3.14159200000000016217427400988526642322540283203125

So when you start multiplying this by 10 in your question code, you can see how it doesn't become an exact integer in a long time (and by then it is far beyond range of int), so your condition is never true (either there is fractional part, or the double is too large to fit in integer).

In other words, what you ask, counting digits directly from a double, makes no sense. You first need to print it as string, otherwise you don't really have a number of decimal digits to count. Of course you could micro-optimize this and skip the actual conversion to ASCII or UTF-16 string, but I don't see a scenario where that would be worth the trouble (except perhaps as a learning excercise).

If you need exact decimal digits in calculations, you need a special number type, which doesn't store fractions in binary. Example of such numeric type is Java BigDecimal.

Number of decimal digits in C

There are two separate issues here: The precision of the floating point number stored, which is determined by using float vs double and then there's the precision of the number being printed as such:

float foo = 0.0123456789;
printf("%.4f\n", foo); // This will print 0.0123 (4 digits).

double bar = 0.012345678912345;
printf("%.10lf\n", bar); // This will print 0.0123456789

Find number of decimal places in decimal value regardless of culture

I used Joe's way to solve this issue :)

decimal argument = 123.456m;
int count = BitConverter.GetBytes(decimal.GetBits(argument)[3])[2];

Count number of digits after `.` in floating point numbers?

The problem isn't really solvable as stated, since floating-point is typically represented in binary, not in decimal. As you say, many (in fact most) decimal numbers are not exactly representable in floating-point.

On the other hand, all numbers that are exactly representable in binary floating-point are decimals with a finite number of digits -- but that's not particularly useful if you want a result of 2 for 3.44.

When I run your code snippet, it says that 3.44 has 2 digits after the decimal point -- because 3.44 * 10.0 * 10.0 just happens to yield exactly 344.0. That might not happen for another number like, say, 3.43 (I haven't tried it).

When I try it with 1.0/3.0, it goes into an infinite loop. Adding some printfs shows that no becomes exactly 33333333333333324.0 after 17 iterations -- but that number is too big to be represented as an int (at least on my system), and converting it to int has undefined behavior.

And for large numbers, repeatedly multiplying by 10 will inevitably give you a floating-point overflow. There are ways to avoid that, but they don't solve the other problems.

If you store the value 3.44 in a double object, the actual value stored (at least on my system) is exactly 3.439999999999999946709294817992486059665679931640625, which has 51 decimal digits in its fractional part. Suppose you really want to compute the number of decimal digits after the point in 3.439999999999999946709294817992486059665679931640625. Since 3.44 and 3.439999999999999946709294817992486059665679931640625 are effectively the same number, there's no way for any C function to distinguish between them and know whether it should return 2 or 51 (or 50 if you meant 3.43999999999999994670929481799248605966567993164062, or ...).

You could probably detect that the stored value is "close enough" to 3.44, but that makes it a much more complex problem -- and it loses the ability to determine the number of decimal digits in the fractional part of 3.439999999999999946709294817992486059665679931640625.

The question is meaningful only if the number you're given is stored in some format that can actually represent decimal fractions (such as a string), or if you add some complex requirement for determining which decimal fraction a given binary approximation is meant to represent.

There's probably a reasonable way to do the latter by looking for the unique decimal fraction whose nearest approximation in the given floating-point type is the given binary floating-point number.

How to determine the number of decimal places in a number?

Not really, the number of decimal places is a function of the internal representation of the number. What you see when you display the number is, is the number as a string for printing.

So if you are interested in the displayed value, you can control the number of decimal places with formatting directives in the first place e.g., %5.2f, or use the string function approach as you mention in your post after the fact once you have the number as a string.

Also, as an aside, would you count trailing zeros?

Perhaps it would be helpful to state your goal for wanting to do this? There might be other ways to accomplish what you are looking to do.

Update:

Based on your update, the problem is really not counting decimal places, rather you are running into represenation issue/rounding errors (not that uncommon). The problem is that some fractional values can't be exactly represented in base 2. Here's an exhaustive explanation: What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Take a look at this SO question: Understanding floating point representation errors; what's wrong with my thinking?

You can try this approach to round the value:

float rounded_val = floorf(value * 100.0 + 0.5) / 100.0; 

Wikipeadia has a whole article on rounding.

Counting and getting highest number of digits after decimal

It's not impossible, it should be pretty easy actually. Cast it to a string, get the substring of the results starting at the decimal and count the result.

For this you will need to look up:

-casting 
-indexof
-substring

If you give it a try and can't figure out comment and I will offer you a little more guidance but you should try it yourself first.

EDIT:

I don't see much of an attempt to do what I suggested, it looks like you just posted the code you had. So here is some pseudo code for you to work with:

string stringNum =  to_string(decimalNum);
int decimalPos = stringNum.find(".");
string newString = stringNum.substr(decimalPos);
int answer = newString.length();

I pretty well answered it for you, you need to figure out the syntax.



Related Topics



Leave a reply



Submit