Check if calculation exceeds MaxValue - c#

I currently got the following method, which is returning me percent-values. For example for an item-price of $350,000 and a percentage of 7%, it returns 24,500.
public static decimal GetPercentValue(decimal? percentage, decimal baseValue)
{
decimal result = 0m;
if (percentage != null)
{
try
{
result = Convert.ToDecimal(baseValue * percentage / 100m);
}
catch (OverflowException)
{
result = 0;
Logger.Warn("OverflowException caught in GetPercentValue() - should better be handled UI-Sided!");
}
}
return result;
}
I don't think this is handled the right way, so is there any way to avoid an exception in this situation?
An OverflowException is being thrown when a user enters an insane number like 999,999,999,999,999,999 and calculates 9999999999% of it. This way I can't check percentage or baseValue for <= decimal.MaxValue simply because they aren't... The calculation result itself then exceeds the decimal range.

This is an old question, but I ran into a similar issue, and thought to provide a possible alternate solution. The problem happens when some calculation of two numbers produces a number greater than a MaxValue. This causes an exception, and is hard to test in the usual way:
decimal existingValue = decimal.MaxValue;
decimal newValue = (decimal)100;
//doesn't work -- exception thrown here
if(existingValue + newValue <= decimal.MaxValue)
{
}
The solution that seems to work for me (without using a Try-Catch block) is to rewrite the equation, in this case as a subtraction:
if(decimal.MaxValue - existingValue >= newValue)
{
//DoSomething
}
MaxValue isn't exceeded because of the subtraction. I haven't tried a multiplication/division example, but I'm guessing it would work too.

The error handling should (most likely) be done outside the method. Right now you're hiding exceptions and returning wrong results (0 is returned when an error occures). The caller of your method cannot tell if the result is correct or if it's due to an OverflowException.
I'd rewrite the method like that:
public static decimal GetPercentValue(decimal? percentage, decimal baseValue)
{
if (percentage == null)
return 0;
return baseValue*(percentage.Value/100);
}
And optionally add a validation method that the user can call to check the parameters before calling the real method.. validation errors could be displayed in the UI:
public static string ValidatePercentValue(decimal? percentage, decimal baseValue)
{
try
{
GetPercentValue(percentage, baseValue);
return null;
}
catch (Exception ex)
{
return ex.Message;
}
}
Besides that note that...
baseValue*(percentage.Value/100)
... is better than...
baseValue*percentage.Value/100
Try to calculate 100% of decimal.MaxValue. The first one works while the second one throws an OverflowException.

Related

Try... catch: test if statement is true

I want to test if my decimal Add is smaller than MAXVALUE and bigger than MINVALUE, with a Try... Catch Method. And if the numbers are bigger than MAXVALUE or smaller than MINVALUE the code should throw an Exception.
But my Code isn't working.
public static decimal Add(decimal number1, decimal number2)
{
decimal Add = number1 + number2;
try
{
Add > RESULT_MAXVALUE;
Add < RESULT_MINVALUE;
}
catch(Exception)
{
//Do Stuf
}
}
I don't want to use if... else!
It depends on the language that you're using, but the convention is that the try block contains statements that can throw exceptions, and thrown exceptions are caught by the catch() blocks following the try. You need to explicitly throw an exception before it can be caught.
It looks like you're using C#. Consider reading https://msdn.microsoft.com/en-us/library/0yd65esw.aspx for more information about try-catch statements in C#.
Using exceptions in your case may not be necessary. Consider using an if statement, like this:
decimal result = a + b;
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
// Do stuff.
}
But to answer your question more directly, here's how you would do it using exceptions:
decimal result = a + b;
try
{
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
throw new System.ArithmeticException(); // Or make an exception type.
}
}
catch (System.ArithmeticException e)
{
// Do stuff.
}
Or perhaps you would throw the exception in Add, but not catch it. Then it would be the caller's responsibility to handle the exception, or let the program crash. That would look like this:
// Adds two numbers. Throws a System.ArithmeticException if the result
// is greater than MAX_VALUE or less than MIN_VALUE.
public static decimal Add(decimal a, decimal b)
{
decimal result = a + b;
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
throw new System.ArithmeticException(); // Or make an exception type.
}
}
And callers would need to wrap calls to Add in a try {} catch if they expect some results to be bigger than MAX_VALUE or less than MIN_VALUE (or, callers could not catch the exception and the program would crash).

I am trying to create a function for a calculator. I want the program to try to parse a string given to transform it to an double number

I am trying to create a function for a calculator. I want the program to try to parse a string given to transform it to an double number. My function has the following form:
private double readOperator(String stringOper)
{
try
{
double oper;
oper = double.Parse(stringOper);
return oper;
}
catch (Exception ex)
{
MessageBox.Show("Wrong Input");
throw ex; // Without this I have to return a double value (no null allowed)
}
}
PROBLEM: I need the function to return a double value so to be able to access it on from the main program as a double. But if the parsing fails (it has chars inside) the only way to get buy the debuger is to either return a double value (not good as the user must be able to input whatever double value he wishes) or to throw an exception which freezes the program.
I don't really need any kind of handling instead of informing the user to change his input, as it is a form. But by throwing the exception the program crashes (as it should). If I continue to run the program by allowing Windows to do so when they ask me everything runs as I want to run. But obviously I don't want the user to go through this process!
Solution: how can I handle the throwing of this exception not to crash the program (to do nothing at all) or how could I return a null/special type of value to handle this? Using public variables is not a good programming method which can easily solve this issue
So handle it (to inform user is handling the exception) in main method:
static void main()
{
try
{
Console.Write("Enter first operand: ");
double a = readOperand(Console.ReadLine());
Console.Write("Enter second operand: ");
double b = readOperand(Console.ReadLine());
// Do something with them
}
catch (FormatException)
{
Console.WriteLine("You didn't enter a floating point number.");
}
}
Or, better, do not even throw exceptions (it's a good practice if you can avoid them: invalid user input isn't an exceptional situation):
double a;
if (!Double.TryParse(Console.ReadLine(), out a))
Console.WriteLine("You didn't enter a floating point number.");
In case your input validation is something more (for example range checking too) than a Double.TryParse() (and you want to keep it in a separate function) then you have two options:
return a nullable value (double? in this case) where null means invalid input.
mimic TryParse behavior and prototype: bool TryReadOperand(string operand, out double value). Simply return false for invalid inputs (decide where to output error message, I would suggest Main because it's more common).
First of all, consider using the TryParse method. Secondly the simplest solution is to return double? from your method, and interpret null as parsing failure. However in general returning null as a "special value" is not considered a good design.
Why not just throw an exception (like you do now), and catch and handle it in a place when you call readOperator method?
The way I see it you have two options.
Try catch around every instance of readOperator() and handle the invalid input in that catch statement.
change it to private double? readOperator(string stringOper). double? is double that allows null values so it would be fine to return null.
The following transforms a nullable double into a normal one
//where d is a double?
if (d.HasValue) //Returns true if not null
{
double x = d.Value // Returns the double value of the double? if not null otherwise throws exception
}
else
{
// Handle the null value
}
edit: Kind of duped another user's answer while writing but I'm going to leave mine here for the example
TryParse is a good bet:
private double readOperator(String stringOper)
{
double oper;
if (Double.TryParse(stringOper, out oper))
return oper;
MessageBox.Show("Wrong Input");
return 0;
}
Also, when you throw an exception using throw ex; you're losing your stack trace.
catch (Exception ex)
{
MessageBox.Show("Wrong Input");
throw; // <---- retains stack trace
}

How to properly put statements inside a try-catch block?

I need to execute a lot of statements, one after the other, and I need that when a sigle statement throws an exception the flow of the program continues executing the next statement, for example:
double a = Double.Parse("2.5");
double b = Double.Parse("ADFBBG");
Geometry g = Geometry.Parse("M150,0L75,200 225,200z");
All statements have to be executed, so I need a sort of try-catch blocks in cascade:
double a, b;
Geometry g;
try
{
a = Double.Parse("2.5");
}
catch
{}
try
{
b = Double.Parse("ADFBBG");
}
catch
{}
try
{
g = Geometry.Parse("M150,0L75,200 225,200z");
}
catch
{}
Obviously this is not the most elegant way to write my program. Is there a better way (more elegant, that does not reduce significantly the performance)?
I tried using the Func<TResult> delegate in such a way:
I wrote the following method:
T Try<T>(Func<T> func)
{
try
{
return func();
}
catch
{
return default(T);
}
}
So I can use it like this:
double x = Try(() => Double.Parse("77"));
Geometry g = Try(() => Geometry.Parse("M150,0L75,200 225,200z"));
Other solutions?
Use Double.TryParse.
It returns a value indicating whether the conversion was successfull. So you can use it the following way:
double converted;
bool success = Double.TryParse(value, out converted);
if (success)
{
// Do whatever you want
// The converted value is in the variable 'covnerted'
}
It seems that you don't care about which parse failed but just need a default value is case of failure? If so init your vars first to defaults then parse in a single try-catch:
double a=0.0, b=0.0;
Geometry g = new Geometry();
try
{
a = Double.Parse("2.5");
b = Double.Parse("ADFBBG");
g = Geometry.Parse("M150,0L75,200 225,200z");
}
catch
{
//At least mark that conversion was not succesful
}
Try-catch will only give you a performance hit when an exception is thrown. If all is well the impact of try-catch is minimal. see this question
A bit more elegant then your posted code but at least more concise.
Alternative with using TryParse
double a=0.0, b=0.0;
Geometry g = new Geometry();
Double.TryParse("2.5", out a);
Double.TryParse("ADFBBG", out b);
Geometry.TryParse("M150,0L75,200 225,200z", out g);
But there is a caveat: Geometry doesn't has TryParse implemented... (assuming that you use System.Windows.Media.Geometry)
That brings me to the point:
use your Try<> func, doens't reduce overhead but is clean
validate the string first. Removes the overhead of try but introduces runtime overhead on parsing.
Either way: validating userinput has it costs.
In answer to the main question: How to properly put statements inside a try-catch block?
If you don't care about which statement fails: 1 try-catch.
However: If the first statement fails, the other statement won't get executed. But, your system is already in in failed/corrupted state. Would further processing result in a correct result? (doubt it)
TryParse is more preferable, because you've no performance penalty on throwing and catching exception.
And one more inaccuracy in the above code - no difference between parsed "0" and default(T).
Code's more fast than yours
public static class StringExt
{
public static double ParseDouble(this string value)
{
double result;
Double.TryParse(value, out result);
return result;
}
}
I have answered a similar question a few days ago. If you have a collection of string values, you can use the power of extension methods to do just that.
static public IEnumerable<double> ConvertToDouble(this IEnumerable<string> source)
{
double x = 0;
var result = source.Where(str => Double.TryParse(str, out x))
.Select (str => x);
return result;
}
So put everything in a collection and use .AsEnumerable() followed by ConvertToDouble() extension method. Everything which cannot be parsed, will be ignored without an exception and the result is of type IEnumerable<Double>
Original answer: Convert List<string> to List<int> in C#
/edit: does the downvoter care to explain? The OP has not clarified, why he wants to use try catch and has not explained what has to be done in case of an exception. Hance I assume he does not want to do anything in case an exception is raised.

Tell if string to double/float/int/short/byte is out of range

I have the following:
string outOfRange = "2147483648"; // +1 over int.MaxValue
Obviously if you have anything other than a number this will fail:
var defaultValue = 0;
int.TryParse(outOfRange, out defaultValue);
My question is, since this IS a number, and it WILL fail when you int.TryParse(), how do you tell that it failed because the string was out of the bounds of the container it's stored in?
I'd go with the Try/Catch solution for this scenario.
string outOfRange = "2147483648";
try
{
int.Parse(outOfRange);
}
catch (OverflowException oex)
{
}
catch (Exception ex)
{ }
I know that most people here would recommend avoiding this but sometimes we just have to use it (or we don't have to but it would just save us a lot of time).
here's a little post about the efficiency of Try/Catch.
can parse to decimal and then check range, avoids try/catch
string s = "2147483648";
decimal.Parse(s) > int.MaxValue;
I would attempt to parse, if it fails, then attempt to parse a higher-capacity value. If the higher capacity value passes parsing, then you know it's out of range. If it fails as well, then it's bad input.
string outOfRange = "2147483648"; // +1 over int.MaxValue
int result;
if (!Int32.TryParse(outOfRange, out result))
{
long rangeChecker;
if (Int64.TryParse(outOfRange, out rangeChecker))
//out of range
else
//bad format
}
Unfortunately, I don't think there's a way to do this generically for any type; you'd have to write an implementation for all types. So for example, what do do for Int64? Maybe use BigInteger instead:
string outOfRange = "9223372036854775808"; // +1 over Int64.MaxValue
long result;
if (!Int64.TryParse(outOfRange, out result))
{
BigInteger rangeChecker;
if (BigInteger.TryParse(outOfRange, out rangeChecker))
//out of range
else
//bad format
}
EDIT: double floating point values may be more fun since AFAIK, there's no "BigDecimal" and you may have to also account for values that approach 0 at the very extreme (not sure about that). Possibly you could do a variation on the BigInteger check but you might also have to account for decimal points (probably a simple regex would be best here to have only numbers, an optional negative sign, and only one at most decimal point). If there are any decimal points, you'd have to truncate them out and simply check the integer portion of the string.
EDITx2: Here's a pretty ugly implementation for checking double values too:
// +bajillion over Double.MaxValue
string outOfRange = "90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.1";
double result;
if (!Double.TryParse(outOfRange, out result))
{
string bigIntegerInput = outOfRange;
if (!Regex.IsMatch(bigIntegerInput, #"^-?[0-9]\d*(\.\d+)?$"))
//bad format
int decimalIndex = bigIntegerInput.IndexOf('.');
if (decimalIndex > -1)
bigIntegerInput = bigIntegerInput.Substring(0, decimalIndex);
BigInteger rangeChecker;
if (BigInteger.TryParse(bigIntegerInput, out rangeChecker))
//out of range
else
//bad format
}
But honestly, at this point I think we've just gone off the deep end. Unless you have some real performance bottleneck, or your application has out-of-range values inputted frequently, you might be better off just catching them the odd time it happens as in this answer or perhaps more simply, applying a regex to the input. In my last example, I may have as well just quit after doing the regex anyway (but I don't know off the top of my head if the TryParse implementations are more lenient, allowing for exponential/scientific notation. If so, the regex would have to cover these as well)
string outOfRange = "2147483648"; // +1 over int.MaxValue
int value;
if(! int.TryParse(outOfRange, out value)) {
try {
int.Parse(defaultValue);
} catch(OverflowException e) {
// was overflow
} catch(Exception e) {
// was other reason
}
}
Assuming that there are few cases where the number is too large, the overhead of exception throwing and catching may be tolerable, as the normal cases are handled with the faster TryParse method without involving exceptions.
This would work similar for other numeric data types like floats, ...
You could try parsing with BigInteger.
BigInteger bigInt;
bool isAnOutOfRangeInt = BigInteger.TryParse(input, out bigInt)
&& (bigInt > int.MaxValue || bigInt < int.MinValue);
// if you care to have the value as an int:
if (!isAnOutOfRangeInt)
{
int intValue = (int)bigInt;
}
Use the normal Parse instead of the TryParse. And then use it inside a try/catch because it will give you the appropriate exception. See this for details: http://msdn.microsoft.com/en-us/library/b3h1hf19.aspx. The exception you are looking for is OverflowException.
I would look at using System.Convert.ToInt32(String) as the mechanism to convert things; namely because OverflowException has already been implemented for you.
This is convenient because you can do something simple like
try
{
result = Convert.ToInt32(value);
Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.",
value.GetType().Name, value, result.GetType().Name, result);
}
catch (OverflowException)
{
Console.WriteLine("{0} is outside the range of the Int32 type.", value);
}
catch (FormatException)
{
Console.WriteLine("The {0} value '{1}' is not in a recognizable format.",
value.GetType().Name, value);
}
and the logic is already a part of the standard System library.
The straight forward way would be to instead use Int32.Parse(string s) and catch OverflowException;
OverflowException
s represents a number less than MinValue or greater than MaxValue.

Making a program do absolutely nothing when certain data or wrong answer is put in

I have this crazy idea, I would like a program to not execute anything if the wrong data is put into the console. Such as the alphabet, weird characters. All I want is decimal numbers and a period to be accepted. If the wrong data is typed in, I want the program to STAY there and do absolutely nothing after you hit enter.
My mindset thinks:
if (sum != decimal)
{
// Don't do anything, just leave it as is.
code I have no clue about.
}
Now, you must be thinking, you can't use datatypes for an if statement! Maybe you can, but its not working for me. I'm sorry I'm a big noob.
try
{
Console.WriteLine("Put in the price of the product");
string input = Console.ReadLine();
decimal sum = Convert.ToDecimal(input);
if (sum <= 100)
{
decimal totalprice = sum * .90m;
Console.WriteLine("Your final price is {0:0:00}", totalprice);
}
}
catch
{
}
I was also thinking maybe a try and catch statement would work too, but again, I have no clue what to put in that either.
If your answers could be noob-safe and explained. (Because I want to learn the concept of how this stuff works) that would be nice.
A visual example:
When you hit enter, nothing happens but when you put in the correct datatype, the program will continue.
Datatypes are not written to console. Only strings could be retrieved from console input. What type has string "2" - decimal, int, byte, string? All you can do is try to parse some type from your input string:
Int32.TryParse("2", out value)
For your case:
Console.WriteLine("Put in the price of the product");
string input = Console.ReadLine();
decimal sum;
if (!Decimal.TryParse(input, out sum))
{
Console.WriteLine("Decimal number cannot be parsed from your input.");
return;
}
if (sum <= 100)
Console.WriteLine("Your final price is {0:0:00}", sum * 0.90M);
UPDATE
Decimal.TryParse - Converts the string representation of a number to its Decimal equivalent. A return value indicates whether the conversion succeeded or failed. It does not throws an exception if conversion failed.
! Operator - it is NOT operator. The logical negation operator (!) is a unary operator that negates its operand. It is defined for bool and returns true if and only if its operand is false.
So if (!Decimal.TryParse(input, out sum)) verifies if conversion was NOT successful. Then I put a sample message for user and exited from method (if it was your Main method, then program will terminate. But this all is out of your initial question about parsing strings.
Try this (note the while/break pairing):
while (true)
{
string input = Console.ReadLine();
decimal sum;
if (Decimal.TryParse(input, out sum) == true)
{
if (sum <= 100)
{
decimal totalprice = sum * .90m;
Console.WriteLine("Your final price is {0:0:00}", totalprice);
break; // break out of while
}
}
}
The conversion function you are using will I believe throw an exception if it cannot convert the string passed to the requested type. Generally, exceptions should be avoided for controlling program flow, and reserved for truly unexpected situations. Instead, you should look to using a method that doesn't throw an exception, but instead returns a value to indicate success or failure. With this in ind you could try:
try
{
Console.WriteLine("Put in the price of the product");
decimal sum;
// Repeat forever (we'll break the loop once the user enters acceptable data)
while (true)
{
string input = Console.ReadLine();
// Try to parse the input, if it succeeds, TryParse returns true, and we'll exit the loop to process the data.
// Otherwise we'll loop to fetch another line of input and try again
if (decimal.TryParse(input, out sum)) break;
}
if (sum <= 100)
{
decimal totalprice = sum * .90m;
Console.WriteLine("Your final price is {0:0:00}", totalprice);
}
}
catch
{
}

Categories