TryParse failing with negative numbers - c#

I'm having a problem getting TryParse to work correctly for me. I have a list of values that I am almost assured are valid (as they come from another component in our system) but I would like to make sure there is proper error handling in place.
Here is an example list of my values:
20.00
20.00
-150.00
And here is the method I originally wrote:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal successful;
Decimal.TryParse(xElement.Value, out successful);
if (successful > 0)
totalValue += Decimal.Parse(xElement.Value);
}
return totalValue;
}
The variable 'successful' was returning false for -150.00, so I added NumberStyles:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal successful;
Decimal.TryParse(xElement.Value, NumberStyles.AllowLeadingSign, null, out successful);
if (successful > 0)
totalValue += Decimal.Parse(xElement.Value, NumberStyles.AllowLeadingSign);
}
return totalValue;
}
However, now that I have the NumberStyles in there, none of the numbers will parse! I feel good about having IFormatProvider set to null as this is all within our system. Does anyone see what I may be doing wrong?

This is not how you are supposed to use TryParse.
TryParse returns a boolean (true/false), so your code above should be:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal valueReturned;
bool successful = Decimal.TryParse(xElement.Value, out valueReturned);
if (successful)
totalValue += valueReturned;
}
return totalValue;
}
or more succinctly,
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal valueReturned;
if (Decimal.TryParse(xElement.Value, out valueReturned))
totalValue += valueReturned;
}
return totalValue;
}

Others are explaining how to do it right, but not really explaining what you're doing wrong.
Where you're using "successful" above isn't the success value, it's the actual number that is being parsed. So if you're parsing "-150.00" of course successful will be negative. The out value of TryParse is the actual parsed value and the boolean indicating whether the process was successful or not is the returned value. Using what you have to help understand would be something like:
string inputValue = "-150.00";
decimal numericValue;
bool isSucessful = Decimal.TryParse(inputValue , out numericValue);
In this case, isSuccessful will be TRUE, numericValue will be -150. When you're using user-provided values instead of the hardcoded one I used above you'll want to check:
if(isSuccessful)
{
// Do something with numericValue since we know it to be a valid decimal
}
else
{
// Inform User, throw exception, etc... as appropriate, Don't use numericValue because we know it's wrong.
}

The other answers have got the right idea with regard to the proper way to use Decimal.TryParse. However, if I were writing the method in question, I'd use LINQ to work with LINQ-to-XML objects:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
return summaryValues
.Sum(el =>
{
decimal value;
if (Decimal.TryParse(el.Value, out value))
return value;
return 0M;
});
}
This version works the exact same way, but it uses the Enumerable.Sum method to calculate the total. All I have to supply is an inline function that extracts decimal values from an XElement.

Came in from Google. Answer for me was the incoming culture was wrong - specifically in an incoming JSON file.
Use
totalValue += decimal.Parse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture);
or
bool successful = decimal.TryParse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out value);

your successful is going to be negative for a negative value being parsed. your if (successful > 0) is what's tripping you up.
If they are almost positively going to be valid values, try using Convert.ToDecimal:
decimal val = Convert.ToDecimal(xElement.Value);
Otherwise, change your logic a bit to be more like:
decimal val;
if (Decimal.TryParse(xElement.Value, out val)){
// valid number
}

I would suggest you to tell XElement which node value it should look for as in:
XElement.Element("nodename").Value
Instead of XElement.Value. at least that is what I would do :)

Related

how do i check the result is between two numbers?

I have read the second line in a text file which contains 2.75 and I am trying to get it to do something if it meets certain criteria. I'm sure I have done this before and has a simple answer but I can't seen to figure it out.
string SecondLine;
using (var reader = new StreamReader(SPFile2))
{
reader.ReadLine();
SecondLine = reader.ReadLine();
}
int NewValue;
NewValue = Convert.ToInt32(SecondLine);
if ((NewValue >= 2) && (NewValue <= 2.99))
{
// Do Something
}
if ((NewValue >= 3) && (NewValue <= 3.99))
{
// Do something else
}
What have I missed out?
You are converting a decimal number to an Int32 that does not hold decimals. This will turn the number in NewValue into 2 as it truncates towards zero. You need to store the variable in a double, float or decimal whichever is best for your requirements.
See the following example that uses a double and Parse:
double newValue = Double.Parse(secondLine);
Note that if you are unsure if the value will be a double you should use Double.TryParse
double newValue;
bool result = Double.TryParse(secondLine, out newValue);
if (!result) //Parse failed
Note that if the parsing fails it may be down to your culture settings i.e. a ',' for the decimal separator not a '.'. However there is an overload for Parse and TryParse that allows you to pass culture information in.
You are trying to parse a string that represents a double into a integer
that will cause a
System.IFormatException
{"Input string was not in a correct
format."}{"Input string was not in a correct format."}
if you know it is a number with decimal part then do:
var newValue = Convert.ToDouble(secondLine);
if you know it is an integer then try:
var newValue = Convert.ToInt32(secondLine);

Conversion XmlNode.InnerText to Double

The condition Double.TryParse(node.ChildNodes[4].InnerText, out course) doesn't work. It's always return 0.
foreach (XmlNode node in XmlDoc.SelectNodes("/ValCurs/Valute"))
{
if (node.ChildNodes[1].InnerText == curr_name) // CharCode
{
// throw new Exception(node.ChildNodes[4].InnerText); //returns 2.085 but the next condition doesn't work
if (Double.TryParse(node.ChildNodes[4].InnerText, out course)) // course value, nominal = 100
{
if (Int32.Parse(node.ChildNodes[2].InnerText) == 10) course *= 10; //for RUB, BYR nominal = 10
if (Int32.Parse(node.ChildNodes[2].InnerText) == 1000) course /= 10; //for JPY, HUF nominal = 1000
return course;
}
}
XML fragment
<Valute id="1">
<NumCode>036</NumCode>
<CharCode>AUD</CharCode>
<Nominal>100</Nominal>
<Name>Australian dollars</Name>
<Value>1276.6300</Value>
</Valute>
TryParse method uses the current culture thus the number formats might differ depending on you system.
You can use the override version of TryParse where you pass IFormatProvider as a parameter. CultureInfo.InvariantCulture uses . as a decimal separator:
Double.TryParse(node.ChildNodes[4].InnerText, CultureInfo.InvariantCulture, out course)
Btw. checking values by throwing them as exceptions is rather interesting approach, but I highly recommend debugging/logging to check what is happening.

check if value is numeric and greater than 0

I have value 0.075445054945055 for a variable corrected count and have the following function. Basically I need a function which would see if the value is a numeric and greater than 0. My current function only works for integers and not for values like 0.075 etc.
The field correctedCount comes from a file when its parsed.
var correctedCount
int num;
bool isNumeric = int.TryParse(correctedCount, out num);
if (isNumeric)
{
}
You can use decimal.TryParse or double.TryParse
You could treat it as a double like so:
double num;
if (double.TryParse(correctedCount, out num))
{
// it's at least a number, now verify it's > 0
return num > 0;
}
else
{
return false;
}
Edit: this works because numbers without decimal parts (e.g., "4") are still valid doubles, as well as "0.075"

converting double/floating to integer in C#

My question might looks like silly, but i struck with it.
I have a string value "155.300" and i want to convert it to integer.
I tryed but throwing System.FormatException....pls someone help me out.
Since your source data is string you need to Convert it to Double first then just cast it to int or use Convert.ToInt32, but remember Convert.ToInt32 rounds it to nearest integer number, whereas casting takes the int part of the number (truncate)
double d = Convert.ToDouble("155.00");
int a = (int) d;
int b = Convert.ToInt32(d);
Or in a single Line
int b =(int) Convert.ToDouble("155.000");
EDIT
Since you want to use decimal point as thousand separator, I believe in German culture you can try the following.
int b = ((int)Convert.ToDouble("154.500", new CultureInfo("de-DE")));
That will give you 154500
EDIT 2
Or much better is to use int.Parse with NumberStyles.AllowThousands:
int b = int.Parse("154.500", NumberStyles.AllowThousands, new CultureInfo("de-DE"));
First parse it as a decimal or double (probably best to use decimal as you've got decimal data) then either cast or use something like Math.Round, depending on your requirements.
Basically, you need to always consider what data you've got: "155.300" isn't a string representation of an integer, so don't try to parse it as an integer. Parse it as what it is, then convert that to an integer.
Alternatively, you could hack at the string representation first, but personally I find that to be a more brittle approach in many cases.
EDIT: Note that if this is really already an integer, but with a thousands separator, you don't need to use double at all - you can use int.Parse, specifying an appropriate culture and number style:
int parsed = int.Parse(text, NumberStyles.Integer | NumberStyles.AllowThousands,
culture);
Here is a working conversion sample. Take a special look with the edge conditions, the output may be different if using several rounding/casting techniques
class Program
{
public static int MyToInt(string str)
{
double result;
bool success = Double.TryParse(str, out result);
if (!success)
{
throw new ArgumentException(
"Cannot parse a string into a double");
}
return Convert.ToInt32(result); // 156
//return (int)result; // 155 <<
//return (int)Math.Round(result); // 156
}
static void Main(string[] args)
{
string s = "155.500";
int value = MyToInt(s);
}
}
You can try this:
string str = "123.123";
str = str.Remove(str.IndexOf('.'), 1);
int result;
int.TryParse(str, out result);
Edit: Based on your comment, modified to multiply by thousand.
Or you can just try:
string str = "123.123";
double result;
double.TryParse(str, out result);
int final = (int)(result * 1000);

check for valid number input - console application

I have a little problem with a simple console application in which i would like to detect if the user inputs a correctly formatted numerical value.
That is, values such as 1212sss or anything like asjkq12323 or a single character is not accepted. I would like to only accept pure integer values.
Here is what i have tried
bool detectNumber(string s)
{
int value=0;
Int.TryParse(s,out value);
return (value!=0)?true:false;
}
I appreciate any help. Thank you soooo much,,,,,
TryParse returns a boolean. Check that, not the value passed via the out parameter.
if( int.TryParse( s, out value ) )
{
// do something
}
Or just:
return int.TryParse( s, out value );
Incidentally, it is not necessary to initialize a value passed using the out keyword. The method declaring the parameter must initialize it before returning.
int foo; // legal
int.TryParse( "123", out foo );
All BCL "Try" methods follow the same convention (such as double.TryParse() for floating point numbers, as #gdoron mentioned in the comments).
And for the curious, source code for the underlying library which implements int.TryParse().
int value = 0;
bool ok = int.TryParse(s, out value);
return ok;
string line = Console.ReadLine();
int value;
if (int.TryParse(line, out value))
{
Console.WriteLine("Integer here!");
}
else
{
Console.WriteLine("Not an integer!");
}
There are several ways to test for only numeric numbers:
first of all, never use Int because of it's maximum value, either use int or Int32.
Parse
int result;
if (int.TryParse("123", out result))
{
Debug.WriteLine("Valid integer: " + result);
}
else
{
Debug.WriteLine("Not a valid integer");
}
Convert.ToInt32()
// throws ArgumentNullExceptionint
result1 = Int32.Parse(null);
// doesn't throw an exception, returns 0
int result2 = Convert.ToInt32(null);
IsNumeric()
using Microsoft.VisualBasic;
// ......
bool result = Information.IsNumeric("123");
Pattern Matching
string strToTest = "123";
Regex reNum = new Regex(#"^\d+$");
bool isNumeric = reNum.Match(strToTest).Success;
Your code works normal, you can only refactor it a bit. Following code is shorter but does exactly the same:
static bool IsInt32(string s)
{
int value;
return Int32.TryParse(s, out value);
}

Categories

Resources