I have a method that returns the perimeter of a triangle. One of the parameters to this method is the precision.
When I call my function specifying the precision I don't get the results I expect. I don't know how I can resolve the problem with Math.Round
.
public static double TrianglePerimeter(int a, int b, int c, int precision = 2)
{
if (a < 0 || b < 0 || c < 0 || precision < 2 || precision > 8)
throw new ArgumentException("wrong arguments");
if (a b < c || a c < b || b c < a)
throw new ArgumentException("object not exist");
return Math.Round((double)a (double)b (double)c, precision);
}
Example:
a = 1, b = 2, c = 3, precision = 3
- Result = 6.000
a = 1, b = 1, c = 1, precision = 5
- Result = 3.00000
CodePudding user response:
As others have pointed out, decimal rounding won't get you what you need because 12 = 12.0 = 12.000. The Round function will only work for you if you actually have significant digits that extend to those decimal places (e.g. 12.0011 would round to 12.001 if you did Math.Round(12.0011, 3);
What you need to do is format the return value as a string with the proper format. Notice the return result is string, not double. Something like this:
public static string TrianglePerimeterS(int a, int b, int c, int precision = 2)
{
if (a < 0 || b < 0 || c < 0 || precision < 2 || precision > 8)
throw new ArgumentException("wrong arguments");
if (a b < c || a c < b || b c < a)
throw new ArgumentException("object not exist");
// Build the format string in the format of "0.000" if precision is 3
string formatString = "0." new string('0', precision);
double value = Math.Round((double)a (double)b (double)c, precision);
string result = value.ToString(formatString);
return result;
}
CodePudding user response:
When you call Math.Round with a precision parameter that is greater than 0, it will round the number to the specified number of decimal places. For example, if you call Math.Round(3.1415, 2), it will return 3.14.
However, when you call Math.Round with a precision parameter that is 0 or less, it will round the number to the nearest integer. For example, if you call Math.Round(3.1415, 0), it will return 3.
In your TrianglePerimeter method, you're calling Math.Round with a precision parameter of 2, which means that it will round the result to 2 decimal places. However, since the perimeter of a triangle is always an integer (it's the sum of the lengths of the sides of the triangle), the result will always be rounded down to the nearest integer.
For example, if a = 1, b = 1, and c = 1, then the perimeter of the triangle is 3. When you call Math.Round with precision = 2, it will round 3.0 down to the nearest integer, which is 3. This is why you're not getting the result you expect.
To fix this problem, you can change your TrianglePerimeter method so that it doesn't call Math.Round with a precision parameter. Instead, it can simply return the sum of the side lengths as an integer:
public static int TrianglePerimeter(int a, int b, int c)
{
if (a < 0 || b < 0 || c < 0)
throw new ArgumentException("All side lengths must be non-negative.");
if (a b < c || a c < b || b c < a)
throw new ArgumentException("Triangle with given side lengths does not exist.");
return a b c;
}
Alternatively, if you still want to use the precision parameter, you can change the return type of the TrianglePerimeter method to double and return the result of calling Math.Round with a precision parameter of 0, which will round the result to the nearest integer:
public static double TrianglePerimeter(int a, int b, int c, int precision = 0)
{
if (a < 0 || b < 0 || c < 0 || precision < 0 || precision > 8)
throw new ArgumentException("Invalid arguments.");
if (a b < c || a c < b || b c < a)
throw new ArgumentException("Triangle with given side lengths does not exist.");
return Math.Round((double)a (double)b (double)c, precision);
}