"Intelligent" cast of double to two differently formatted strings? - c#

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);
}
}

Related

String Comparison or Parse to Int?

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.

How to Know whether Variable Contains a integers or Strings?

I just want to know, whether a variable contains a positive integer value.
Currently I am doing:
int APPOeeVersion =
Convert.ToInt32(ConfigurationManager.AppSettings["OEEVersion"]);
Here i just want to know whether APPOeeVersion Contains Int value or not. If not Need to show a error message as it is invalid format. Please help me out i have checked with several forums but not find exact solution.
Use int.TryParse, It will not raise an exception in case of failure and would give you bool value back if parsing was successful/unsuccessful.
string str = "1234";
int APPOeeVersion;
if (int.TryParse(str, out APPOeeVersion))
{
//parsing successful
}
else
{
//not an integer
}
If parsing is successful you will get the value of parsed string in your out parameter.
For checking a positive number and parsing you can have the check like:
if (int.TryParse(str, out APPOeeVersion) && APPOeeVersion > 0)
If you want to test for a positive integer, then you might need to use uint.TryParse since int.TryParse will allow negative values.
uint appoEeVersion;
var oeeVersionValue = ConfigurationManager.AppSettings["OEEVersion"];
if(!uint.TryParse(OEEVersionValue , out appoEeVersion))
{
// Error, not a positive integer
}
else
{
// Success, user value
}
int.TryParse would be the method: http://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx
int APPOeeVersion;
if(!int.TryParse(ConfigurationManager.AppSettings["OEEVersion"], out APPOeeVersion) || APPOeeVersion < 0){
//throw error
}
//use variable APPOeeVersion
I'm a little confused by your wording. Do you mean the variable is an integer or contains an integer?
If the former, then the solutions posted will work fine.
Are you guaranteed that the variable will only ever be an integer with no decimal notation (eg: 2 vs 2.0)? If not, you might need to use decimal.parse instead.
Integer parsing will fail on the other decimal values since they are not valid integers.
Decimal APPOeeVersion;
if (Decimal.TryParse(input,out APPOeeVersion))
{
Console.WriteLine("Successfully parse: {0} to {1}", input, APPOeeVersion);
}
else
{
Console.WriteLine("Failed to parse {0}", input);
}
Console.Write("\nEnter a number to test: ");
Then then use additional logic to ensure that the result is positive.
If you want to know whether it contains an integer, then a regular expression like the ones found here will work.
Maybe I'm just dumb or overthinking this, but it seems like you have to give a few more constraints

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.

Creating a percentage type in C#

My application deals with percentages a lot. These are generally stored in the database in their written form rather than decimal form (50% would be stored as 50 rather than 0.5). There is also the requirement that percentages are formatted consistently throughout the application.
To this end i have been considering creating a struct called percentage that encapsulates this behaviour. I guess its signature would look something like this:
public struct Percentage
{
public static Percentage FromWrittenValue();
public static Percentage FromDecimalValue();
public decimal WrittenValue { get; set; }
public decimal DecimalValue { get; set; }
}
Is this a reasonable thing to do? It would certianly encapsulate some logic that is repeated many times but it is straightforward logic that peopel are likely to understand. I guess i need to make this type behave like a normal number as much as possible however i am wary of creating implicit conversions to a from decimal in case these confuse people further.
Any suggestions of how to implement this class? or compelling reasons not to.
I am actually a little bit flabbergasted at the cavalier attitude toward data quality here.
Unfortunately, the colloquial term "percentage" can mean one of two different things: a probability and a variance. The OP doesn't specify which, but since variance is usually calculated, I'm guessing he may mean percentage as a probability or fraction (such as a discount).
The extremely good reason for writing a Percentage class for this purpose has nothing to do with presentation, but with making sure that you prevent those silly silly users from doing things like entering invalid values like -5 and 250.
I'm thinking really more about a Probability class: a numeric type whose valid range is strictly [0,1]. You can encapsulate that rule in ONE place, rather than writing code like this in 37 places:
public double VeryImportantLibraryMethodNumber37(double consumerProvidedGarbage)
{
if (consumerProvidedGarbage < 0 || consumerProvidedGarbage > 1)
throw new ArgumentOutOfRangeException("Here we go again.");
return someOtherNumber * consumerProvidedGarbage;
}
instead you have this nice implementation. No, it's not fantastically obvious improvement, but remember, you're doing that value-checking in each time you're using this value.
public double VeryImportantLibraryMethodNumber37(Percentage guaranteedCleanData)
{
return someOtherNumber * guaranteedCleanData.Value;
}
Percentage class should not be concerned with formatting itself for the UI. Rather, implement IFormatProvider and ICustomFormatter to handle formatting logic.
As for conversion, I'd go with standard TypeConverter route, which would allow .NET to handle this class correctly, plus a separate PercentageParser utility class, which would delegate calls to TypeDescriptor to be more usable in external code. In addition, you can provide implicit or explicit conversion operator, if this is required.
And when it comes to Percentage, I don't see any compelling reason to wrap simple decimal into a separate struct other than for semantic expressiveness.
It seems like a reasonable thing to do, but I'd reconsider your interface to make it more like other CLR primitive types, e.g. something like.
// all error checking omitted here; you would want range checks etc.
public struct Percentage
{
public Percentage(decimal value) : this()
{
this.Value = value
}
public decimal Value { get; private set; }
public static explicit operator Percentage(decimal d)
{
return new Percentage(d);
}
public static implicit operator decimal(Percentage p)
{
return this.Value;
}
public static Percentage Parse(string value)
{
return new Percentage(decimal.Parse(value));
}
public override string ToString()
{
return string.Format("{0}%", this.Value);
}
}
You'd definitely also want to implement IComparable<T> and IEquatable<T> as well as all the corresponding operators and overrides of Equals, GetHashCode, etc. You'd also probably also want to consider implementing the IConvertible and IFormattable interfaces.
This is a lot of work. The struct is likely to be somewhere in the region of 1000 lines and take a couple of days to do (I know this because it's a similar task to a Money struct I wrote a few months back). If this is of cost-benefit to you, then go for it.
This question reminds me of the Money class Patterns of Enterprise Application Architecture talks about- the link might give you food for thought.
Even in 2022, .Net 6 I found myself using something just like this. I concur with Michael on his answer for the OP and like to extend it for future Googlers.
Creating a value type would be indispensable in explaining the domain's intent with enforced immutability. Notice especially in the Fraction Record you will get a Quotient that would normally cause an exception however here we can safely show d / 0 with no error, likewise all other inherited children are also granted that protection (It also offers an excellent place to establish simple routines to check validity, data rehydration (as if DBA's don't make mistakes), serialization concerns just to name a few.)
namespace StackOverflowing;
// Honor the simple fraction
public record class Fraction(decimal Dividend, decimal Divisor)
{
public decimal Quotient => (Divisor > 0.0M) ? Dividend / Divisor : 0.0M;
// Display dividend / divisor as the string, not the quotient
public override string ToString()
{
return $"{Dividend} / {Divisor}";
}
};
// Honor the decimal based interpretation of the simple fraction
public record class DecimalFraction(decimal Dividend, decimal Divisor) : Fraction(Dividend, Divisor)
{
// Change the display of this type to the decimal form
public override string ToString()
{
return Quotient.ToString();
}
};
// Honor the decimal fraction as the basis value but offer a converted value as a percentage
public record class Percent(decimal Value) : DecimalFraction(Value, 100.00M)
{
// Display the quotient as it represents the simple fraction in a base 10 format aka radix 10
public override string ToString()
{
return Quotient.ToString("p");
}
};
// Example of a domain value object consumed by an entity or aggregate in finance
public record class PercentagePoint(Percent Left, Percent Right)
{
public Percent Points => new(Left.Value - Right.Value);
public override string ToString()
{
return $"{Points.Dividend} points";
}
}
[TestMethod]
public void PercentScratchPad()
{
var approximatedPiFraction = new Fraction(22, 7);
var approximatedPiDecimal = new DecimalFraction(22, 7);
var percent2 = new Percent(2);
var percent212 = new Percent(212);
var points = new PercentagePoint(new Percent(50), new Percent(40));
TestContext.WriteLine($"Approximated Pi Fraction: {approximatedPiFraction}");
TestContext.WriteLine($"Approximated Pi Decimal: {approximatedPiDecimal}");
TestContext.WriteLine($"2 Percent: {percent2}");
TestContext.WriteLine($"212 Percent: {percent212}");
TestContext.WriteLine($"Percentage Points: {points}");
TestContext.WriteLine($"Percentage Points as percentage: {points.Points}");
}
 PercentScratchPad
Standard Output: 
TestContext Messages:
Approximated Pi Fraction: 22 / 7
Approximated Pi Decimal: 3.1428571428571428571428571429
2 Percent: 2.00%
212 Percent: 212.00%
Percentage Points: 10 points
Percentage Points as percentage: 10.00%
I strongly recommend you just stick with using the double type here (I don't see any use for the decimal type either, as wouldn't actually seem to require base-10 precision in the low decimal places). By creating a Percentage type here, you're really performing unnecessary encapsulation and just making it harder to work with the values in code. If you use a double, which is customary for storying percentages (among many other tasks), you'll find dealing with the BCL and other code a lot nicer in most cases.
The only extra functionality that I can see you need for percentages is the ability to convert to/from a percentage string easily. This can be done very simply anyway using single lines of code, or even extension methods if you want to abstract it slightly.
Converting to percentage string :
public static string ToPercentageString(this double value)
{
return value.ToString("#0.0%"); // e.g. 76.2%
}
Converting from percentage string :
public static double FromPercentageString(this string value)
{
return double.Parse(value.SubString(0, value.Length - 1)) / 100;
}
I think you may be mixing up presentation and logic here. I would convert the percentage to a decimal or float fraction (0.5) when getting it from the database and then let the presentation deal with the formatting.
I'd not create a separate class for that - this just creates more overhead. I thinkg it will be faster just to use double variables set to the database value.
If it is common knowledge that the database stores percentages as 50 instead of 0.5, everybody will understand statemens like part = (percentage / 100.0) * (double)value.

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