I have a Oracle-view which gives me those data:
DATUM STUNDE LAUFZEIT
-------------- ---------- -----------
30.10.14 00:00 11 ,433333333
The column LAUFZEIT is declared as NUMBER. Which format to I need to convert the column to get 0,433333333 or rounded to 0,4?
I already tried some types like Convert.ToSingle(reader.GetValue(2)) but always get a error like
System.OverflowException: Arithmetic operation resulted in an overflow
Thanks!
You have to mention a currect Culture:
Object source = ",433333333";
// This will fail with exception - Neutral Culture uses decimal point, not comma
//Single single = Convert.ToSingle(source, CultureInfo.InvariantCulture);
// OK: Russian culture (ru-RU) uses decimal comma, not decimal point
Single single = Convert.ToSingle(source, new CultureInfo("ru-RU"));
To represent the value in desired form, use formatting, e.g. for 0,4:
// F1 - one floating point
// "ru-RU" for decimal comma
String result = single.ToString("F1", new CultureInfo("ru-RU"));
Edit: having seen on the Exception stack trace, i.e.
Arithmetic operation resulted in an overflow. at Oracle.DataAccess.Types.DecimalConv.GetDecimal(IntPtr numCtx)
one can conclude that the problem is in the
`Oracle.DataAccess.Types.DecimalConv.GetDecimal`
the origin of the error may be in the fact that Oracle Number(36) or the the like is bigger that .Net Decimal. Since you can't change Oracle.DataAccess library you can convert to String just in the query:
select ...
cast(LAUFZEIT as VarChar2(40)),
...
you can always add a leading zero yourself before parsing. Adding a zero to the start of a number will NEVER change it.
Convert.ToSingle('0' + reader.GetString(2).Replace(',','.')) should do it.
I advice to use reader.GetString() before parsing.
Also it would be better to do:
Single a ;
if(Single.TryParse('0' + reader.GetString(2).Replace(',','.')), out a))
{
//Success code here
}
else
{
//Code to execute if string was not parsable here
}
In this way you won't get an exception
Related
I tried to figure out the basics of these numeric string formatters. So I think I understand the basics but there is one thing I'm not sure about
So, for example
#,##0.00
It turns out that it produces identical results as
#,#0.00
or
#,0.00
#,#########0.00
So my question is, why are people using the #,## so often (I see it a lot when googling)
Maybe I missed something.
You can try it out yourself here and put the following inside that main function
double value = 1234.67890;
Console.WriteLine(value.ToString("#,0.00"));
Console.WriteLine(value.ToString("#,#0.00"));
Console.WriteLine(value.ToString("#,##0.00"));
Console.WriteLine(value.ToString("#,########0.00"));
Probably because Microsoft uses the same format specifier in their documentation, including the page you linked. It's not too hard to figure out why; #,##0.00 more clearly states the programmer's intent: three-digit groups separated by commas.
What happens?
The following function is called:
public string ToString(string? format)
{
return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
}
It is important to realize that the format is used to format the string, but your formats happen to give the same result.
Examples:
value.ToString("#,#") // 1,235
value.ToString("0,0") // 1,235
value.ToString("#") // 1235
value.ToString("0") // 1235
value.ToString("#.#")) // 1234.7
value.ToString("#.##") // 1234.68
value.ToString("#.###") // 1234.679
value.ToString("#.#####") // 1234.6789
value.ToString("#.######") // = value.ToString("#.#######") = 1234.6789
We see that
it doesn't matter whether you put #, 0, or any other digit for that matter
One occurrence means: any arbitrary large number
double value = 123467890;
Console.WriteLine(value.ToString("#")); // Prints the full number
, and . however, are treated different for double
After a dot or comma, it will only show the amount of character that are provided (or less: as for #.######).
At this point it's clear that it has to do with the programmer's intent. If you want to display the number as 1,234.68 or 1234.67890, you would format it as
"#,###.##" or "#,#.##" // 1,234.68
"####.#####" or "#.#####" // 1234.67890
i have value stored in string format & i want to convert into decimal.
ex:
i have 11.10 stored in string format when i try to convert into decimal it give me 11.1 instead of 11.10 .
I tried it by following way
string getnumber="11.10";
decimal decinum=Convert.ToDecimal(getnumber);
i tried this also
decinum.ToString ("#.##");
but it returns string and i want this in decimal.
what could be the solution for this?
As already commented 11.1 is the same value as 11.10
decimal one=11.1;
decimal two=11.10;
Console.WriteLine(one == two);
Will output true
The # formatter in the to string method means an optional digit and will supress if it is zero (and it is valid to suppress - the 0 in 4.05 wouldn't be suppressed). Try
decinum.ToString("0.00");
And you will see the string value of 11.10
Ideally you actually want to use something like
string input="11.10";
decimal result;
if (decimal.TryParse(input,out result)) {
Console.WriteLine(result == 11.10);
} else {
// The string wasn't a decimal so do something like throw an error.
}
At the end of the above code, result will be the decimal you want and "true" will be output to the console.
this will work perfectly
string getnumber = "11.10";
decimal decinum = Math.Round(Convert.ToDecimal(getnumber), 2);
A decimal datatype stores a value. The value of 11.1 is identical to that of 11.10 - mathemtically, they're the exact same number, so it's behaving properly.
What you seem to want is to display the number as 11.10, but that's up to the code that displays it - I don't know if you're writing to log file, displaying on a web-page or any other format - but that is independent of the internal representation of the decimal datatype.
there is no solution, This is expected behaviour.
11.10 in string = 11.1 in number
you cant store zeros on the decimal part, otherwise 11.10 would be different than 11.100, which is true if you are talking about strings but not if you are talking about numbers.
I think your problem is on a presentation level only. Why dont you explain better what you want to do.
11.10 expressed as a decimal is 11.1, just like it is 11.100000000000000000000000000000000000.
For mathematical processes, don't worry about how it displays itself. If you are displaying the value then converting it into a string is no biggie either. Remember that
decinum.ToString ("#.##");
is returning a string (from the 'ToString' function) and not converting the 'decinum' to a string.
string getnumber = "11.10";
double decinum = double.Parse(getnumber);
I am attempting to validate a date text box to make sure the correct date format was entered.
I converted this vb6 code:
If (IsDate(txtBirthDate)) And (IsNumeric(Right(txtBirthDate, 4))))
into this C# code -
int output = 1;
DateTime output2;
if ((! DateTime.TryParse(txtBirthDate.Text, out output2)) & (!int.TryParse((txtBirthDate.Text.Substring(txtBirthDate.Text.Length - 5)), out output)))
{
MessageBox.Show("error")
}
What I am attempting to do is make sure that the last 4 digits of the date text box are numeric (the year - i.e 1990 in 05/10/1990) and if it is not a number, then show error. Although I cannot verify everything is numeric due to the "/" in the date format.
The code does not show an error and builds. But when I debug the application I receive an error. The error states:
Index and length must refer to a location within the string.
Parameter name: length.
Any ideas on how to accomplish this?
To check if a date is in a specific format, use DateTime.TryParseExact():
if (!DateTime.TryParseExact(output , "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out output2))
{
MessageBox.Show("error")
}
EDIT: Change the format according to your needs:
"d/M/yyyy" for UK and "M/d/yyyy" for US
Edit: It sounds like the cause of your error is your string is too short. Test the string length before you test the last 4 characters.
Three other issues:
The And operator in C# is &&. You are using & which is a bitwise operator.
To check the last four characters of the string, you should use .Length - 4, not 5.
You are negating the return values in your C#, but not in your VB. To match the VB, omit the !. But, it looks like that's not what you are actually trying to do. It looks like you want to show an error message if either the string is not parsable as a date or the year portion is not 4 digits. In that case use a an or comparison (||):
if (!DateTime.TryParse(txtBirthDate.Text, out output2) ||
txtBirthDate.Text.Length < 4 ||
!int.TryParse((txtBirthDate.Text.Substring(txtBirthDate.Text.Length - 4)), out output))
{
MessageBox.Show("error")
}
Keep in mind that yyyy/M/d is also parsable as a Date, contains a 4-digit year, but will fail your test. Is that what you want?
From the error provided it looks like you just need a length check to make sure you can process the code. You should also use && instead of & (or in this case probably ||) to ensure that the boolean expressions stop executing once a true state has been encountered.
if (txtBirthDate.Text.Length < 5 ||
(!DateTime.TryParse(txtBirthDate.Text, out output2) ||
!int.TryParse((txtBirthDate.Text.Substring(txtBirthDate.Text.Length - 5)), out output)))
{
MessageBox.Show("error")
}
However, this might be a good case for the use of a regular expression.
Regex reg = new Regex("^\d{2}/\d{2}/\d{4}$");
if (!reg.IsMatch(txtBirthDate.Text))
MessageBox.Show("error");
Tweaking of the regular expression to match fringe cases (leading zero's, alternate formats, etc) may be necessary.
int result;
if (int.TryParse(txtBirthDate.Text.Substring(test.LastIndexOf("/")), out result))
{
//its good
}
else
{
//its bad
}
I am currently using ncalc library to do several evaluation and get the result out of it.
Right now I have found a problem where if I have a price in the format "1,234.01" it will fail to evaluate my expression.
The current workaround I've used was to remove the , but I was wondering if there is way to evaluate a currency without having to remove the , for example:
decimal price = 0;
if (!decimal.TryParse(iPrice.Text, out price))
{
MessageBox.Show("Price is not formatted correctly...");
return;
}
decimal currency = 0;
if (!decimal.TryParse(iCurrency.Text, out currency))
{
MessageBox.Show("Currency is not formatted correctly...");
return;
}
string formula = iFormula.Text.Replace("Price", price.ToString("n2")).Replace("Currency", currency.ToString("n2"));
Expression exp = new Expression(formula);
exp.Evaluate();
Evaluate fails because of the , from my price where if I remove it, it works just fine.
Sample of the formula:
(((Price+12,9)+((Price+12,9)*0,05)+(((Price+12,9)+((Price+12,9)*0,05))*0,029)+0,45)*Currency)
Stacktrace as requested:
NCalc.EvaluationException was unhandled
Message=mismatched input ',' expecting ')' at line 1:4
mismatched input ',' expecting ')' at line 1:20
mismatched input ',' expecting ')' at line 1:43
mismatched input ',' expecting ')' at line 1:59
missing EOF at ')' at line 1:77
Source=NCalc
StackTrace:
at NCalc.Expression.Evaluate()
Your question is still unclear to me, but I suspect you can fix this just by changing the format you're using when replacing. Change this:
string formula = iFormula.Text.Replace("Price", price.ToString("n2"))
.Replace("Currency", currency.ToString("n2"));
to this:
string formula = iFormula.Text.Replace("Price", price.ToString("f2"))
.Replace("Currency", currency.ToString("f2"));
That will use the "fixed point" format instead of the "number" format. You won't get grouping. Note that grouping isn't part of the number itself - it's part of how you format a number.
I'd also be tempted to specify the invariant culture explicitly, by the way.
As an aside: I haven't used NCalc myself, but if it's really forcing you to specify the numeric values in an expression as text, that sounds pretty poor. I'd expect some sort of parameterization (as per most SQL providers, for example) which should make all of this go away.
No, you cannot have a separator in your decimal literal. The compiler will confuse it with declaring multiple variables with the same type like:
decimal price = 1m, tax = 234m;
If it was a string, however, you could parse it like:
decimal price = Decimal.Parse("1,234.0", CultureInfo.InvariantCulture);
EDIT: my answer above was directed to the code sample in the first version of the question. Now that the question has been edited:
You can control the string representation of your decimal values using the Decimal.ToString(string format, IFormatProvider provider) method overload. This allows you to specify a standard or custom format string. In your case, it sounds like you need to have 2 decimal digits separated using a dot, and no group separators (no commas). So you could say:
price.ToString("F2", CultureInfo.InvariantCulture) // ex. result: "1234.56"
CultureInfo.InvariantCulture is important if you need a dot separator regardless of the current culture. If you don't specify that, the output could be "1234,56" depending on the current culture (e.g. in case of european cultures like de-DE, or fr-FR).
How do I prevent the code below from throwing a FormatException. I'd like to be able to parse strings with a leading zero into ints. Is there a clean way to do this?
string value = "01";
int i = int.Parse(value);
Your code runs for me, without a FormatException (once you capitalize the method properly):
string value = "01";
int i = int.Parse(value);
But this does ring an old bell; a problem I had years ago, which Microsoft accepted as a bug against localization components of Windows (not .NET). To test whether you're seeing this, run this code and let us know whether you get a FormatException:
string value = "0"; // just a zero
int i = int.Parse(value);
EDIT: here's my post from Usenet, from back in 2007. See if the symptoms match yours.
For reference, here's what we found.
The affected machine had bad data for
the registry value
[HKEY_CURRENT_USER\Control Panel
\International\sPositiveSign].
Normally, this value is an empty
REG_SZ (null-terminated string). In
this case, the string was missing its
terminator. This confused the API
function GetLocaleInfoW(), causing it
to think that '0' (ASCII number zero)
was the positive sign for the current
locale (it should normally be '+').
This caused all kinds of havoc.
You can verify this for yourself with
regedit.exe: open that reg value by
right-clicking on the value and
selecting 'Modify Binary Data'. You
should see two dots on the right
(representing the null terminator).
If you see no dots, you're affected.
Fix it by adding a terminator (four
zeros).
You can also check the value of
CultureInfo.CurrentCulture.NumberFormat.PositiveSign;
it should be '+'.
It's a bug in the Windows localization
API, not the class libs. The reg
value needs to be checked for a
terminator. They're looking at it.
...and here's a report on Microsoft Connect about the issue:
Try
int i = Int32.Parse(value, NumberStyles.Any);
int i = int.parse(value.TrimStart('0'));
TryParse will allow you to confirm the result of the parse without throwing an exception. To quote MSDN
Converts the string representation of
a number to its 32-bit signed integer
equivalent. A return value indicates
whether the operation succeeded.
To use their example
private static void TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
if (value == null) value = "";
Console.WriteLine("Attempted conversion of '{0}' failed.", value);
}
}
You don't have to do anything at all. Adding leading zeroes does not cause a FormatException.
To be 100% sure I tried your code, and after correcting parse to Parse it runs just fine and doesn't throw any exception.
Obviously you are not showing actual code that you are using, so it's impossible to say where the problem is, but it's definitely not a problem for the Parse method to handle leading zeroes.
Try
int i = Convert.ToInt32(value);
Edit: Hmm. As pointed out, it's just wrapping Int32.Parse. Not sure why you're getting the FormatException, regardless.
I have the following codes that may be helpful:
int i = int.Parse(value.Trim().Length > 1 ?
value.TrimStart(new char[] {'0'}) : value.Trim());
This will trim off all extra leading 0s and avoid the case of only one 0.
For a decimal number:
Convert.ToInt32("01", 10);
// 1
For a 16 bit numbers, where leading zeros are common:
Convert.ToInt32("00000000ff", 16);
// 255