String Comparison or Parse to Int? - c#

I'll keep this one short. I'm writing a module which will be required to compare two large integers which are input as strings (note: they are large, but not large enough to exceed Int64 bounds).
The strings are padded, so the choice is between taking the extra-step to converting them to their integer equivalent or comparing them as strings.
What I'm doing is converting each of them to Int64 and comparing them that way. However, I believe that string comparisons would also work. Seeing as I'd like it to be as efficient as possible, what are you're opinions on comparison of integers via :
string integer1 = "123";
string integer2 = "456";
if (Int64.Parse(integer1) <= Int64.Parse(integer2))
OR
string integer1 = "123";
string integer2 = "456";
if (integer1.CompareTo(integer2) < 0)

Better to use Int64.TryParse since this is a string fields
string integer1 = "123";
string integer2 = "456";
long value1=0;
long value2=0;
long.TryParse(integer1 ,out value1);
long.TryParse(integer2 ,out value2);
if(value1<=value2)

Nope string comparisons will not work. You should use your first version, you have to convert this strings to numbers parsing them and then compare the numbers.
It would be good to have a look here, where explains thorougly what the CompareTo method does. In a few words:
Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
So since "123" and "456" are strings, they compare one string to another and not the one integer to the other.
Last but not least, it would be better to use the TryParse method for parsing your numbers, since your input may be not accidentally an integer. The way you use it is fairly easy:
Int64 value = 0;
Int64.Parse(integer1, out value1);
Where the value1 is the value1 you will get after the conversion of the string integer1. So for both you values, you should use this one if statement:
if(Int64.TryParse(integer1, out value1) && Int64.TryParse(integer2, out value2)
{
if(value1<=value2)
{
}
else
{
}
}
else
{
// Some error would have been happened to at least one of the two conversions.
}

It's fair to question if it is worth the cost of conversion (parse). If String.CompareTo were really efficient AND the number were always of a scale and format* the the string comparison were to be reliable then you might be better off. You could measure the performance, but you'll find the convert and int comparision is faster and more robust than a string comparison.
*String compare works if number strings are of equal length with leading 0s as necessary. So '003','020', and '100' will sort correctly but'3','20', and '100' will not.

Related

Function Int32.TryParse("23.0") returning false - C# MVC4

In my code i try to get browser version for charging the good css file, but this code doesn't work, and i don't see my error...
I've simply try first with a Convert.ToInt32 but don't works too...
public ActionResult Index()
{
ViewBag.logged = false;
ViewBag.BrowserName = Request.Browser.Browser.ToString();
Int32 v = 0;
string version = Request.Browser.Version;
if (version != null)
{
bool result = Int32.TryParse(version, out v);
}
ViewBag.BrowserVersion = v;
return View();
}
In my debugger :
version => string : "23.0"
v => int 0
result => false
Request.Browser.Version => string "23.0"
This is by design.
Parsing a version string would work better with System.Version.
You can, alternatively, parse it to a float and then see if a lossless conversion to Int32 can be made.
I fully agree with Andrei's answer; that's the approach you should take.
However, I think it's important to note that there is a way to parse int values from strings such as "23.0": it can be done using this overload of int.TryParse() which allows you to pass NumberStyles flags as parameters.
Concretely, after executing this code:
int v;
var wasParsedOK = Int32.TryParse(
"23.0",
NumberStyles.AllowDecimalPoint,
CultureInfo.InvariantCulture,
out v);
v will hold the value 23 and wasParsedOK will be true.
You can't assume that the version string is going to be integral, or even decimal. A browser could perfectly report 7.0b as its version. None of int, float, decimal or System.Version can represent this.
If you're only concerned about the major and minor version numbers, you can use the MajorVersion and MinorVersion properties of your Browser object, assuming it is of type HttpBrowserCapabilities. The framework has done the parsing for you, so it should be reliable.
It is giving false because 23.0 is not an int, So you can try with decimal,double or float.
decimal v = 0;
string version = "23.0";
Decimal.TryParse(version, out v);
It's been almost 2 years and no one has answered this correctly. The question is simple, "Why is it returning false?"
This question has already been answered, simply because your string is not an Integer, but is a Double or Decimal. By design, TryParse will try to get the EXACT match of the type integer from your string, if not it will return false, and your string ("23.0") is not an exact match.
Now if you're trying to find a solution in converting your version string to a number, What you can do is filter out the non-numeric, excluding 1 dot (.), in the string, then convert what's left to decimal/double. After this conversion you can then try converting it integer. Since you already converted your stirng to double/decimal, you can no longer use TryParse because the parameter needs to be in string format. You can then use Convert.ToInt32 inside a Try block.

dividing efficiently

I want to divide a number of type double, by an int. I only need the result in 2 deicmal place in string format. What is the best way to do this in terms of stack efficiency?
double d=321321321313131233213213213213;
int i=123;
ToString(d/i); //what do I get when I do this? A double? A float?
public String ToString(float? result) //what should I cast the result?
{
return #String.Format("{0:#,0.##;} divided double by int", result);
}
ToString(d/i); //what do I get when I do this? A double? A float?
You'll get a double. Dividing a double by an int will result in a double value.
public String ToString(float? result) //what should I cast the result?
You'll get a double for the value, so you'd be better off just using a double here. You'll never get a nullable type, and definitely wouldn't get a float as a result, so using float? is wholly inappropriate.
What is the best way to do this in terms of stack efficiency?
This is really not worth worrying about, unless, of course, you profile and find this really happens to be a problem. Building the string will be far more expensive than the division operation, and neither is likely to be a hotspot in terms of performance.
A clean way to handle this would just be to use double.ToString("N2"), ie:
double result = d/i;
string resultAsString = result.ToString("N2");
If you want a full, formatted string, you can use:
string resultAsString = string.Format("{0:N2} divided double by int", result);
Ok. First off, you get double, not double? or float?. Math functions should never return a nullable type. If you are assuming that infinity is represented as null, you are wrong. Infinities are determined by the bits. You can see if a double is infinity with Double.IsInfinity(double).
[SecuritySafeCritical]
public static unsafe bool IsInfinity(double d)
{
return ((*(((long*) &d)) & 0x7fffffffffffffffL) == 0x7ff0000000000000L);
}
What is the best way to do this in terms of stack efficiency?
I would recommend a look at the tragedies of micro optimization over at Coding Horror.
As for the function. That is completely unnecessary. Your best bet is Double.ToString(...):
double val = d / i;
string result = val.ToString("N2");
However, if you are using String.Format(...), you can use:
double val = d / i;
string result = string.Format("{0:N2} divided double by int", val);
Hacky solution:
If you need only 2 decimal places, you can multiply your double by 100, convert it to an integer, and then divide it by i.
Now take the string of the result, and add a dot before the last two chars.
Don't forget to handle the edge cases of negative values and rounding problems.
If you really care about efficiency, division of fractions is a slow process in comparison to division of integers.

Equality comparison of the datatype of two strings value in C#

This is a weird requirement I have. I know even my question is quite confusing. Here is what I want to know.
I've two string variables. I need to do equality comparison of the datatype of the underlying value in the string variables. For ex.
string firstVariable = "123"; // It contains integer value. i.e. I can convert it to integer value
string secondVariable = "string" // It contains string value.
Now I need to compare whether datatype of the underlying values of these two strings are same. How can I do this?
Update: Thanks to all for the clarifications and answers. How about if I know the type of one variable?
For ex:
int firstVariable;
string secondVariable = "123".
Is this possible to check whether the type of the first variable equals to converted value of the secondVariable. When I declared firstVariable as int it doesn't mean it is always int type. What I mean here is, I know the type of one variable and other variable is string and I want compare equality of the datatypes of firstvariable and value datatype of the secondVariable.
Is Convert.ChangeType will anyway help in the above scenario?
I know this is silly question, but out of curiosity in the language feature exploring, I wanted to know this.
There's no such thing as the "underlying data type".
Who's to say that "123" isn't just a string containing the digits 1, 2 and 3? Once you've converted a value to a string, any information about the value you converted from - including its type - is lost.
Written from my head so there may (will) be errors:
class StringTypeEqualityComparer : IEqualityComparer<string, string>
{
public bool Equals(string x, string y)
{
int tempInt;
if (Int32.TryParse(x, out tempInt) && (Int32.TryParse(y, out tempInt))
return true;
bool tempBool;
if (Boolean.TryParse(x, out tempBool) && Boolean.TryParse(y, out tempBool))
return true;
float tempFloat;
if (Single.TryParse(x, out tempFloat) && Single.TryParse(y, out tempFloat))
return true;
// And whatever other types you want to compare...
return false;
// But what if two regular strings should also evaluate to equal?
}
}
Why do you need to compare them by the underlying data type?. Just compare them as string. Or if you have another variable as string, just convert it to a string by calling ToString() and make the comparison on the string level.
To do it you have to have a limited list of possible data types and be sure that type of your string content is not ambiguous. Then, for each type, you can try to convert string to it, so you will be able to find what type it actually was.

"Intelligent" cast of double to two differently formatted strings?

I'm working with a database that has the limit that the only (numeric) datatype it can store is a double. What I want to do is pick the number for a certain row and put it into an HTTP request. The problem revolves around that I cannot know if this number should or should not have decimals.
For example, if the double is an ID, I cannot have any kind of formatting whatsoever, since the site that gets the HTTP request will be confused. Observe the following examples:
site.com/showid.php?id=12300000 // OK
site.com/showid.php?id=1.23E7 // Bad; scientific notation
site.com/showid.php?id=12300000.0 // Bad; trailing decimal
The solution to this would be to cast it to a long. Ignoring the problem of overflowing the long, it solves the scientific notation and (obviously) trailing decimal. This could be an acceptable solution but it would be nice if the code didn't assume it were IDs we were dealing with. What if, for example, I were to query a site that shows a map and the number are coordinates, where the decimals are very important? Then a cast to long is no longer acceptable.
In short;
If the double has no decimals, do not add a trailing decimal.
If it has decimals, keep them all.
Neither case should have scientific notation or thousand separators.
This solution will be ported to both C# and Java so I accept answers in both languages.
(Oh, and I had no idea what to call this question, feel free to rename if you got something better.)
To complement the answer of gustafc (who beat me by 1 minute), here's the relevant code line for C#:
MyDouble.ToString("0.################")
or
string.Format("{0:0.################}", MyDouble);
Since it is safe to format the value with no trailing zeroes if it is integral (whether it represents an ID or a coordinate), why not just codify the logic you describe in your bullet points? For example (C#, but should translate readily to Java):
// Could also use Math.Floor, etc., to determine if it is integral
long integralPart = (long)doubleValue;
if ((double)integralPart == doubleValue)
{
// has no decimals: format it as an integer e.g. integralPart.ToString("D") in C#
}
else
{
// has decimals: keep them all e.g. doubleValue.ToString("F17")
}
How about encapsulating the number in a custom type?
public class IntelligentNumber
{
private readonly double number;
public IntelligentNumber(double number)
{
this.number = number;
}
public override string ToString()
{
long integralPart = (long)this.number;
if((double)integralPart == this.number)
{
return integralPart.ToString();
}
else
{
return this.number.ToString();
}
}
}
See also Vilx-'s answer for a better algorithm than the one above.
check whether num == round(num)
In Java, you can do this with DecimalFormat.
static String format(double n) {
return new DecimalFormat("0.###########################").format(n);
}
The # placeholders won't show up unless the number something other than zeros to put there, and the decimal point doesn't show up unless there's something following it.
Heres my own conclusion:
Check if the double has decimals.
Depending on that, format the string accordingly.
And then something important; without specifying an invariant culture, the comma in the has-decimals case may be a "," instead of a "." which isnt liked by HTTP requests. Of course, this problem only crops up if your OS is set to a locale that prefers the comma.
public static string DoubleToStringFormat(double dval)
{
long lval = (long)dval;
if ((double)lval == dval)
{
// has no decimals: format as integer
return dval.ToString("#.", CultureInfo.InvariantCulture);
}
else
{
// has decimals: keep them all
return dval.ToString("0.##################", CultureInfo.InvariantCulture);
}
}

C# doubt, finding the datatype

I have the following variables:
string str1 = "1";
string str2 = "asd";
string str3 = "3.5";
string str4 = "a";
Now I need to find the data type of each string i.e. the data type to which it can be converted if quotes are removed. Here is what I would like each variable to convert to:
str1 - integer
str2 - string
str3 - double
str4 - char
Note: if the string has single character it should be char, though a string can have single letter, I'm limiting it.
FYI: these values are obtained from DataGrid where i manually entered values. So everything is becoming a string.
Is there any way to do this?
Of course, there's no definite way to do this, but if you create a list of data types you want to check ordered by priority, then something like this may do the trick.
object ParseString(string str)
{
int intValue;
double doubleValue;
char charValue;
bool boolValue;
// Place checks higher if if-else statement to give higher priority to type.
if (int.TryParse(str, out intValue))
return intValue;
else if (double.TryParse(str, out doubleValue))
return doubleValue;
else if (char.TryParse(str, out charValue))
return charValue;
else if (bool.TryParse(str, out boolValue))
return boolValue;
return null;
}
Just call this function on each string, and you should have the appropiate type of object returned. A simple type check can then tell you how the string was parsed.
Use meta-data, if you can
That you have to guess what the data types are, is not a good idea.
Two things
1 Where is the data coming from?
If it's a database, are you sure they're strings?
If it is a database, there should be some meta data returned that will tell you what the datatypes of the fields are.
If it's an Xml file, is there a schema defined that will give you the types?
2 If you have to continue to guess.
Be aware that you can have strings that happen to be numbers, but are perfectly valid strings e.g phone numbers, bank acount numbers, that are best expressed as strings.
Also these numbers can have many digits, if you convert them to doubles you may loose some digits to floating point inaccuracies (you should be OK up to 14 or 15 digits)
I'm sure by now - cause I've taken my time typing this - there are lots of answers telling you how to do this (i.e. tryparse int first, then double, then test length for char, if not then it's a string etc), but if I were you, I'd try to NOT do that, and see if there's any way you can get, or pass some meta-data that will tell you what type it IS and not just what type it might be
Use the TryParse method of each type.
There is no built in way to do this, you could attempt TryParse on number types with increasing precision, but it wouldn't guarantee it to be right.
Your best bet what be to process it like you would manually. i.e. Is there a decimal place? No - then its an integer. How big? Is it negative?
The datatype for each of these items is string. If you want to attempt to parse them into different types you can use Int32.TryParse, Double.TryParse, etc. Or you can use Regex:
bool isInt = new Regex(#"^\d+$").IsMatch(str);
bool isDouble = !(isInt) && new Regex(#"^\d+\.\d+$").IsMatch(str);
bool isChar = !(isInt || isDouble) && new Regex(#"^.$").IsMatch(str);
bool isString = !(isInt || isDouble || isChar);

Categories

Resources