Find Number of Decimal Places in Decimal Value Regardless of Culture

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];

Get number of total decimal places in decimal (including non-significant ones)

Thanks to @V4Vendetta for pointing me to the other question.

This does the trick:

int count = BitConverter.GetBytes(decimal.GetBits(yourDecimalHere)[3])[2];

(From: https://stackoverflow.com/a/13493771/70140)

Get number of digits in a decimal variable

If you need to get the number of logical digits, IE stripping out trailing zeroes I suggest you use the accepted approach here:

Find number of decimal places in decimal value regardless of culture

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

I've used this approach in multiple projects and it works really nicely. Note that this is for finding the number of trailing decimal points (I assumed that's what you're after but it's not clear from your question).

How to check if a decimal number is in range of unsigned int 32?

The unsigned long type shall have at least 32 bits, so it should be able to represent any uint32_t value.

That means that you should be able to use std::strtoul to convert argv[1] and then control that unsigned long has same rank as uint_32_t or that the value is not greater that 2**32 -1.

How to get the next decimal given a decimal/precision

You seem to be looking for something like this: (Check below if you want to specify the precision manually)

static decimal GetNextDecimal(decimal input)
{
int count = BitConverter.GetBytes(decimal.GetBits(input)[3])[2];
return input + (1m / (decimal)Math.Pow(10, count));
}

Usage:

decimal num1 = 0.0000041m;
decimal num2 = 0.00002m;
decimal next = GetNextDecimal(num1);
decimal next2 = GetNextDecimal(num2);
Console.WriteLine(next);
Console.WriteLine(next2);

Output:

0.0000042
0.00003

I used a little help of this answer to get the number of the decimal places.


If you originally wanted to specify the precision manually, you can use the following instead:

static decimal GetNextDecimal(decimal input, int precision)
{
return input + (1m / (decimal)Math.Pow(10, precision));
}

..which allows you to do something like this:

decimal num1 = 0.003m;
decimal next = GetNextDecimal(num1, 3);
decimal next2 = GetNextDecimal(num1, 4);
Console.WriteLine(next);
Console.WriteLine(next2);

Output:

0.004
0.0031

System.FormatException if use new CultureInfo( id-ID ) - Indonesian culture

In id-ID, the decimal separator (CultureInfo.NumberFormat.NumberDecimalSeparator) is ",", so it is expecting "1,2162876E-5" as the input (meaning the numeric value zero point zero zero zero zero one two etc). If the input is using a "." to mean decimal point, then you should probably use the invariant culture to parse it (CultureInfo.InvariantCulture), instead of a locale-specific culture.

How do I covert the decimal places of a double to a string?

You could convert the double to a string, then get the substring:

double a = 1.05;

// Convert to string
string aString = a.ToString();

// Get substring
string result = aString.Substring(aString.LastIndexOf('.'));

// Get number of decimals
int numDecimals = result.Length - 1;

// Create string based on decimal count
string zeroString = ".";
for (int i = 0; i < numDecimals; i++) {
zeroString += "0";
}

Console.WriteLine(result);
Console.WriteLine(numDecimals);
Console.WriteLine(zeroString);
// .05
// 2
// .00

** To ensure this works for all cultures and not only those who utilize '.' as the decimal separator, you could replace:

LastIndexOf('.')

with

LastIndexOf(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator)

(Thanks @John)

Returning a specific amount of decimals in C

Since you are summing integers, you could multiply the average by 10 in the integer domain, and divide by 10 in the real domain.

double avg(int* grade, int len){
int i; int sum=0;

for(i=0;i<len;i++){
sum+=grade[i];
}

return (sum * 10 / len) / 10.0;
}

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.



Related Topics



Leave a reply



Submit