Parsing in CSharp - how to understand it - c#

It's just few days ago that I jumped into learning C# and I already have one problem with understanding basics.. Maybe it's just the language barrier (I'm not English native speaker). Please, could you explain me how to understand parsing? For example: while creating a very simple calculator I wanted to read the first input number (which is a variable a). I use this code:
float a = float.Parse(Console.ReadLine());
and the same with b for the other number:
float b = float.Parse(Console.ReadLine());
I learnt that the float is a data type for decimals numbers so what exactly does this particular Parse() stands for?
Obviously, I tried to run the application without parsing and it wouldn't work because it reads it as string, but why? Thank you..

Console.ReadLine() returns a string, which represents a piece of text. So, from the computer's point of view, what you have after calling Console.ReadLine() is a piece of text. It may or may not contain the text "6.0", but from the computer's point of view, it is just a piece of text. As such, you cannot use it to add, subtract etc.
Using the float.Parse(...) method, you tell the computer: "This piece of text actually represents a floating point number, could you please read the text and give me back a number, so that I can start doing math with it?".

The method you are using, float.Parse() is just one of many such methods that take a String input value, and attempt to convert it into the target type, here a float.
There is a safer alternative, however, and it is TryParse():
float a;
if (float.TryParse(Console.ReadLine(), out a))
{
//do something with your new float 'a'
}
In either case, your are asking the framework to inspect the value you provide, and attempt to make a conversion into the requested type. This topic can be quite deep, so you'll want to consult MSDN for the specifics.

Console.ReadLine reads text that the user inputs and returns it to the program so that you may do with it what you want. Therefore, the ReadLine method returns a string.
If you want to work with a decimal (check the decimal class instead of float), you need to convert the string, which is a character sequence, to a number of your desired type, that's where float.Parse comes in:
float.Parse accepts a string and if possible, returns a float value.
Almost every type contains the Parse method which is used to transform a string into the calling one.

Related

Spliting a number into equal parts and Add it together to get the same number

I need to implement a logic in c# where as I need to split and Add it to together to get the same value.
For example:
1.0/6.0442137639369475 = 0.16544749061764519
and when I add
0.16544749061764519 + 0.16544749061764519
to make it 1.0 is not working at all it comes as
0.99268494370587
not 1.0 exactly.
I am not sure what I am missing...?
Try to use more precise dataformats. Try to use double. If this is not precise enough, what I doubt, you can still search for a more precise implementation.
if I guess your question correct, you want to do the following math:
c=a/b
d=c+c+c+... n-times until a==d.
this will only work if you use integer numbers for a and b, with your real number 6.0442137639369475 as b it cannot (math law afaik).
And by the way:
your division result 0.16544749061764519 is rounded! The correct result is 0.16544749061764518326.
So you maybe need another data type as already pointed out.

Testing database field types for compatibility

I have some generic database routines. One that I make use of quite frequently is based on code similar to this code, but for an OleDbDataReader, not the generic IDataReader from that code.
I was playing around with this, and decided to test what would if I tried to (say) retrieve a value from a field, where I had input the incorrect type. Eg: I try to get a double value from a database column that is actually an integer:
reader.GetValue<double>("Column_that_is_Integer_Type");
...and, unexpectedly, it seamlessly converts the database column integer value to a double. Hmm. OK - I get a usable value back, but what about other conversions?
reader.GetValue<bool>("Column_that_is_Integer_Type");
This returns true. Not exactly what I want, and I get no error.
reader.GetValue<DateTime>("Column_that_is_Integer_Type");
This one at least throws an InvalidCast Exception.
Because of all this, I added the follow type checks to the code:
if (theReader.GetFieldType(fieldIndex) == typeof(T))
{
//Carry on...
}
else
{
//Raise an error
}
I think this is the safest way of preventing issues, but was wondering if there is a somewhat 'generic' compatibility check that can be performed? My onward use of a given variable probably won't care whether '39.5' retrieved from a database that stores it as a double is passed around as a decimal, but it will certainly care if it is being passed around as a bool.
My default position will be to throw an error if someone gets the column data type wrong, but I was interested enough to ask the question: Is there a robust method for checking whether type conversions preserve appropriate data integrity?
Eg. Integer type converted to Double: OK. Double converted to Integer: Nope.
Double type converted to Decimal: OK. Double converted to DateTime: Nope.
I think I've answered my own question, but interested in opinions.

String contains trailing zeroes when converted from decimal

I've run into an unusual quirk in a program I'm writing, and I was trying to figure out if anyone knew the cause. Note that fixing the issue is easy enough. I just can't figure out why it is happening in the first place.
I have a WinForms program written in VB.NET that is displaying a subset of data. It contains a few labels that show numeric values (the .Text property of the labels are being assigned directly from the Decimal values). These numbers are being returned by a DLL I wrote in C#. The DLL calls a webservice which initially returns the values in question. It returns one as a string, the other as a decimal (I don't have any control over the webservice, I just consume it). The DLL assigns these to properties on an object (both of which are decimals) then returns that object back to the WinForm program that called the DLL. Obviously, there's a lot of other data being consumed from the webservice, but no other operations are happening which could modify these properties.
So, the short version is:
WinForm requests a new Foo from the DLL.
DLL creates object Foo.
DLL calls webservice, which returns SomeOtherFoo.
//Both Foo.Bar1 and Foo.Bar2 are decimals
Foo.Bar1 = decimal.Parse(SomeOtherFoo.Bar1); //SomeOtherFoo.Bar1 is a string equal to "2.9000"
Foo.Bar2 = SomeOtherFoo.Bar2; //SomeOtherFoo.Bar2 is a decimal equal to 2.9D
DLL returns Foo to WinForm.
WinForm.lblMockLabelName1.Text = Foo.Bar1 //Inspecting Foo.Bar1 indicates my value is 2.9D
WinForm.lblMockLabelName2.Text = Foo.Bar2 //Inspecting Foo.Bar2 also indicates I'm 2.9D
So, what's the quirk?
WinForm.lblMockLabelName1.Text displays as "2.9000", whereas WinForm.lblMockLabelname2.Text displays as "2.9".
Now, everything I know about C# and VB indicates that the format of the string which was initially parsed into the decimal should have no bearing on the outcome of a later decimal.ToString() operation called on the same decimal. I would expect that decimal.Parse(someDecimalString).ToString() would return the string without any trailing zeroes. Everything I find online seems to corroborate this (there are countless Stack Overflow questions asking exactly the opposite...how to keep the formatting from the initial parsing).
At the moment, I've just removed the trailing zeroes from the initial string that gets parsed, which has hidden the quirk. However, I'd love to know why it happens in the first place.
It's because the scaling factor also preserves any trailing zeros in a Decimal number. Trailing zeros do not affect the value of a Decimal number in arithmetic or comparison operations. However, trailing zeros might be revealed by the ToString method if an appropriate format string is applied.

c# - Parsing an odd string concatenation to float

I'm working in C# and trying to parse out the floats on each side of the "w" from the following string:
"10.3w20.5"
I want to have the floats available to use as floats in an equation. How do I accomplish this?
I tried splitting the string by length but then realized that the values on each side could be variable in length.
How about:
var floats = "10.3w20.5".Split('w').Select(s => Convert.ToSingle(s));
The only thing to add to avalable answers, is what usually people forget to mantion in conversion mnagement. If you're going to operate in multiculture environment, pay attention on Culture you use to store and convert data to.
public static float ToSingle(
string value,
IFormatProvider provider
)
I would say, even if you're not going to operate in multiculture environment, it's always a good to pay attention on this.

sql type float, real, decimal?

well in my database i had a colum for price of one product
i had it as float, my problem is if i saved it since my c# application
as 10.50 .. in a query it returns 10,50 and if i update i get a error
10,50 cant convert to float ... or something so..
and if i saved it as decimal, in queries inside sql management .. are ok..
but in my c# application... i get the same error..
10.50 retuns as 10,50 i dont know why, and how to solved it.. my unique solution is saved it
as varchar...
That's a localisation problem of some sort. 10,50 is the "European" way of writing ten and a half. If you're getting that from your select statements then your database is probably configured incorrectly.
Generally speaking you should use the same type throughout your layers. So if the underlying types in the database are x, you should pass around those data with identical types in c#, too.
What type you choose depends on what you are storing--you shouldn't be switching around types just to get something to "work". To that end, storing numeric data in a non-numeric type (e.g. varchar) will come back to bite you very soon. It's good you've opened this question to fix that!
As others have miraculously inferred, you are likely running into a localization issue. This is a great example of why storing numbers as strings is a problem. If you properly accept user input in whatever culture/localization they want (or you want), and get it into a numeric-type variable, then the rest (talking to the DB) should be easy. More so, you should not do number formatting in the database if you can help it--that stuff is much better placed at the front end, closer to the users.
I think your setting in windows regional and language for decimal symbol is wrong.please set it to dot and again test it.
This may help out for temporary use but I wouldn't recommend it for permanent use:
Try making it so that just before you save the file, convert the number to a string, replace the commas with periods (From , to .) and then save it into the database as the string, hopefully it should see that it is in the correct format and turn it into what the database sees as "Decimal" or "Floating".
Hope this helps.
Yep, localization.
That said, I think your pice is being stored on a "money" field in SQLServer (I'm assuming it's SQLServer you're using). If that was a float in the DB, it would return it with a normal decimal point, and not the European money separator ",".
To fix:
Fist DO NO USE FLOAT in your c# code, unless you absolutely require a floating point number. Use the decimal type instead. That's not just in this case, but in all cases. Floating point numbers are binary (base-2), not decimal (base-10), so what you see in the interface is only a decimal approximation of the actual number. The result is that frequently (1 == 1) evaluates as false!
I've run into that problem myself, and it's maddening if you don't know that can happen. Always use decimal instead of float in c#.
Ok, after you've fixed that, then do this to get the right localization:
using System.Globalization;
...
NumberFormatInfo ni = new NumberFormatInfo();
ni.CurrencyDecimalSeparator = ",";
decimal price = decimal.Parse(dbPriceDataField, ni);
Note that "dbPriceDataField" must be a string, so you may have to do a ".ToString()" on that db resultset's field.
If you end up having to handle other "money" aspects of that money field, like currency symbols, check out: http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.aspx
If you need more robust error handling, either put that decimal.Parse in a try/catch, or use decimal.TryParse.
EDIT --
If you know what culture (really, country), the db is set to, you can do this instead:
using System.Globalization;
...
CultureInfo ci = new CultureInfo("fr-FR"); // fr-FR being "french France"
decimal price = decimal.Parse(dbprice, ci.NumberFormat);
Such problems were faced by me in my Web Apps... but i found the solution like I was fetching my price value in textbox. So I was have database attached with that. So when you attached your database with textbox... When you right click textbox and click Edit DataBinding.... in that you have to provide.... type like in Bind Property..... {0:N2}
This will work only for web apps or websites... not for desktop applications...

Categories