Click here to Skip to main content
12,248,339 members (53,144 online)
Rate this:
 
Please Sign up or sign in to vote.
See more: C#
I am using Visual C# 2010 Express and am stumped with the Math.Round method.

Two overloads are important to the context of my question:
1- Math.Round(decimal d, int n)
2- Math.Round(double d, int n)

I am trying to round to 5 total base-10 digits. See code snippet below:

int fractional_digits = 4;
double number_to_round = 123.456789;
double rounded_result = Math.Round(number_to_round, fractional_digits);
number_to_round = 11223344.556677;
rounded_result = Math.Round(number_to_round, fractional_digits);
number_to_round = 876.54321E+57;
rounded_result = Math.Round(number_to_round, fractional_digits);

The code is redundant to show the issue three times. The first rounded result gives 123.4568 not 123.46 (or 1.2346E+2) (1 integer + 4 fractional digits).

The second rounded result is 11223344.5567 instead of 11223000 (or 1.1223E+7).
Lastly, the rounded result is 8.7654321E+59 instead of 8.7654E+59.

I need only 5 significant digits. The code example seems to be using method 1 as shown above - not method 2.

I need method 2. (See comment header copied below).
//
// Summary:
//     Rounds a double-precision floating-point value to a specified number of fractional
//     digits.
//
// Parameters:
//   value:
//     A double-precision floating-point number to be rounded.
//
//   digits:
//     The number of fractional digits in the return value.
//
// Returns:
//     The number nearest to value that contains a number of fractional digits equal
//     to digits.
//
// Exceptions:
//   System.ArgumentOutOfRangeException:
//     digits is less than 0 or greater than 15.
public static double Round(double value, int digits);

How do I force the compiler to use method 2? Any other suggestions?

I have done a basic search for help on this site (via Google) but all examples only show a single place-value in the integer position.

Thanks in advance.

-EJ
Posted 21-Nov-12 7:51am
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 1

A few thoughts that might help:

A double is not an exact representation of a decimal number, it's an approximation, so you might not always get the result you want, just the closest result it can represent.

For numbers less than 100,000, you can easily determine the number of fractional digits you need:
int fractional_digits =  5 - (int)Math.Floor(Math.Log10(number_to_round)) + 1;
(Yes, you could use just 4 - ... instead, but I wrote it this way to make it more clear how it works.)
Math.Floor(Math.Log10(number_to_round)) gives you one less than the number of digits the number has before the decimal place (it makes sense, if you think about how logs and digits work), subtract that from the total and you get the number of digits you want after the decimal point. This will even work for values < 1.

I'm not sure of an obvious way to deal with numbers with more than 5 digits before the decimal point, maybe divide them by a power of 10 to make them shorter, then round, then multiply them by that power of 10 again?
  Permalink  
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 2

Building on the answer by lewax00, I have built a "workaround" as shown below:

int fractional_digits = 4;
double number_to_round = 123.456789;
double rounded_result;
double base_ten_factor = 0;
 
base_ten_factor = Math.Pow(10,(int)Math.Floor(Math.Log10(number_to_round)));
number_to_round = Math.Round(number_to_round / base_ten_factor, fractional_digits);
rounded_result = number_to_round * base_ten_factor;
number_to_round = 11223344.556677;
 
base_ten_factor = Math.Pow(10, (int)Math.Floor(Math.Log10(number_to_round)));
number_to_round = Math.Round(number_to_round / base_ten_factor, fractional_digits);
rounded_result = number_to_round * base_ten_factor;

The first result is 123.46 and the second is 11223000. Just what I need.

Thanks lewax00 for getting me through the mental log-jam.

-EJ
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web01 | 2.8.160426.1 | Last Updated 21 Nov 2012
Copyright © CodeProject, 1999-2016
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100