how the decimal digits is decided in ToString(CultureInfo.NumberFormat) - c#

I met an issue about formatting decimal using CultureInfo in C# today.
I have a decimal fValue has a value of 999, when it runs fValue.ToString(CurrentCulture.NumberFormat) 999.0000 is returned.
While debugging in VS I can get the following values in the Watch window:
fValue //returns 999
fValue.ToString(CurrentCulture.NumberFormat) //the issue returns 999.0000
(999M).ToString(CurrentCulture.NumberFormat) //returns 999
CurrentCulture.NumberFormat.NumberDecimalDigits //returns 2
Why the second value returns 999.0000 rather than 999 or 999.00? Sorry for my crap English someone please help.

Using CurrentCulture.NumberFormat.CurrencyDecimalDigits property you will get the number of decimal digits for Decimal type. 999M type is typeof(Decimal), and it is considered as Currency.

The Decimal struct preserves the precision of the values after parsing from a string, and also as computations are performed. The ToString() method correctly indicates the actual internal precision of the value, regardless of which culture is being used.
However, the debugger appears to display the value in its simplest form instead of showing what ToString() would return, which makes things confusing to say the least.

Related

I'm getting rounding that I don't want when formatting a number in c#

As I understand from Microsoft's documentation, if I have 340550.46 and I apply the format string #,##0.00 I should get the string "340,550.46". But instead, I'm getting "340.550,50". I've set breakpoints to ensure that I know what the number and format strings are going in.
To be more specific, I have a string "340550.46", and I convert it to a float, and then use ToString() to format it with "#,##0.00":
float.Parse("340550.46").ToString("#,##0.00)
What am I doing wrong here? Why is it rounding the number, and what can I do to prevent that?
The reason for the rounding is that a float is limited to 7 signficant digits.
See: https://en.wikipedia.org/wiki/IEEE_754
If you changed to a double, you would get that 8th extra digit. Also, if you are formatting to 2 decimal places since it may be currency, consider using Decimal.

Is there a way to format a C# double exactly? [duplicate]

This question already has answers here:
Formatting doubles for output in C#
(10 answers)
Closed 8 years ago.
Is there a way to get a string showing the exact value of a double, with all the decimal places needed to represent its precise value in base 10?
For example (via Jon Skeet and Tony the Pony), when you type
double d = 0.3;
the actual value of d is exactly
0.299999999999999988897769753748434595763683319091796875
Every binary floating-point value (ignoring things like infinity and NaN) will resolve to a terminating decimal value. So with enough digits of precision in the output (55 in this case), you can always take whatever is in a double and show its exact value in decimal. And being able to show people the exact value would be really useful when there's a need to explain the oddities of floating-point arithmetic. But is there a way to do this in C#?
I've tried all of the standard numeric format strings, both with and without precision specified, and nothing gives the exact value. A few highlights:
d.ToString("n55") outputs 0.3 followed by 54 zeroes -- it does its usual "round to what you probably want to see" and then tacks more zeroes on the end. Same thing if I use a custom format string of 0.00000...
d.ToString("r") gives you a value with enough precision that if you parse it you'll get the same bit pattern you started with -- but in this case it just outputs 0.3. (This would be more useful if I was dealing with the result of a calculation, rather than a constant.)
d.ToString("e55") outputs 2.9999999999999999000000000000000000000000000000000000000e-001 -- some of the precision, but not all of it like I'm looking for.
Is there some format string I missed, or some other library function, or NuGet package or other library, that is able to convert a double to a string with full precision?
You could try using # placeholders if you want to suppress trailing zeroes, and avoid scientific notation. Though you'll need a lot of them for very small numbers, e.g.:
Console.WriteLine(double.Epsilon.ToString("0.########....###"));
I believe you can do this, based on what you want to accomplish with the display:
Consider this:
Double myDouble = 10/3;
myDouble.ToString("G17");
Your output will be:
3.3333333333333335
See this link for why: http://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx
By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
You can also do:
myDouble.ToString("n16");
That will discard the 16th and 17th noise digits, and return the following:
3.3333333333333300
If you're looking to display the actual variable value as a number, you'll likely want to use "G17". If you're trying to display a numerical value being used in a calculation with high precision, you'll want to use "n16".

Double to String Format text format

i have the follwing lines of code
double formId=2013519115027601;
txtEditFormID.Text = formid.ToString();
it gives me output
2.0135191150276E+15
if i write
txtEditFormID.Text = formId.ToString("0.0", CultureInfo.InvariantCulture);
it gives me
2013519115027600.0
but i want the label text
2013519115027601
how to do it?
I don't have enough information about the usage of your formId variable.
As it is shown above it seems an error to use a double datatype when there is no decimals to work on. So redefining your variable as a long datatype will be easy and the conversion will be the same.
long formId=2013519115027601;
txtEditFormID.Text = formid.ToString();
Not to mention the added benefit to your code to work with whole numbers instead of floating point numbers.
However, if you want to maintain the current datatype then
txtEditFormID.Text = formId.ToString("R");
The Round Trip Format Specifier
When a Single or Double value is formatted using this specifier, it is
first tested using the general format, with 15 digits of precision for
a Double and 7 digits of precision for a Single. If the value is
successfully parsed back to the same numeric value, it is formatted
using the general format specifier. If the value is not successfully
parsed back to the same numeric value, it is formatted using 17 digits
of precision for a Double and 9 digits of precision for a Single.
Your first option is to use data type as long or decimal . Something else you can do if you want to keep using double is this :
double formId = 2013519115027601;
string text = formId.ToString();
txtEditFormID.Text = text.Replace(".",string.Empty);
this will remove all the '.' chars
There are times where I want calculations handled in double but I want the result displayed as as an int or even rounded amount, so the question isn't so strange (assuming that the given sample is simplified in order to ask the question).
I was going to post sample code for rounding, but it makes more sense to just use the built-in method Math.Round(). You can cast to a long, as mentioned above, but you won't have rounding, if desired (which it usually is, IMHO).
txtEditFormId.Text = ((long)formId).ToString();

C# Convert.ToDouble() loses decimal points when converting string to double

Let's say we have the following simple code
string number = "93389.429999999993";
double numberAsDouble = Convert.ToDouble(number);
Console.WriteLine(numberAsDouble);
after that conversion numberAsDouble variable has the value 93389.43. What can i do to make this variable keep the full number as is without rounding it? I have found that Convert.ToDecimal does not behave the same way but i need to have the value as double.
-------------------small update---------------------
putting a breakpoint in line 2 of the above code shows that the numberAsDouble variable has the rounded value 93389.43 before displayed in the console.
93389.429999999993 cannot be represented exactly as a 64-bit floating point number. A double can only hold 15 or 16 digits, while you have 17 digits. If you need that level of precision use a decimal instead.
(I know you say you need it as a double, but if you could explain why, there may be alternate solutions)
This is expected behavior.
A double can't represent every number exactly. This has nothing to do with the string conversion.
You can check it yourself:
Console.WriteLine(93389.429999999993);
This will print 93389.43.
The following also shows this:
Console.WriteLine(93389.429999999993 == 93389.43);
This prints True.
Keep in mind that there are two conversions going on here. First you're converting the string to a double, and then you're converting that double back into a string to display it.
You also need to consider that a double doesn't have infinite precision; depending on the string, some data may be lost due to the fact that a double doesn't have the capacity to store it.
When converting to a double it's not going to "round" any more than it has to. It will create the double that is closest to the number provided, given the capabilities of a double. When converting that double to a string it's much more likely that some information isn't kept.
See the following (in particular the first part of Michael Borgwardt's answer):
decimal vs double! - Which one should I use and when?
A double will not always keep the precision depending on the number you are trying to convert
If you need to be precise you will need to use decimal
This is a limit on the precision that a double can store. You can see this yourself by trying to convert 3389.429999999993 instead.
The double type has a finite precision of 64 bits, so a rounding error occurs when the real number is stored in the numberAsDouble variable.
A solution that would work for your example is to use the decimal type instead, which has 128 bit precision. However, the same problem arises with a smaller difference.
For arbitrary large numbers, the System.Numerics.BigInteger object from the .NET Framework 4.0 supports arbitrary precision for integers. However you will need a 3rd party library to use arbitrary large real numbers.
You could truncate the decimal places to the amount of digits you need, not exceeding double precision.
For instance, this will truncate to 5 decimal places, getting 93389.42999. Just replace 100000 for the needed value
string number = "93389.429999999993";
decimal numberAsDecimal = Convert.ToDecimal(number);
var numberAsDouble = ((double)((long)(numberAsDecimal * 100000.0m))) / 100000.0;

.net Parse() round float values

I found one very interesting thing about parsing a string into a float value. The case is that the string value is obtained from a database by using IDbReader Here is an example:
IDbReader myReader;
...
string sValue = myReader.GetValue(0).ToString(); // 12.339123 for example in VS debug and watch
// the content of sValue is what I want to be at this point, but...
Single fValue = Single.Parse(sValue);
// Now the fValue is 12.34!
If I test just Parse for a constant string, the Parse method works fine:
string sValue = "12.339123";
Single fValue = Single.Parse(sValue);
// Now the fValue is 12.339123!
I am not sure why the content of sValue from IDbReader cannot be parsed as original value (as I can see from VS debug). It rounds the float value to a float value with 2 digits after decimal point. How can I get the original value?
How I can get the exactly same value back?
I am using .Net 2.0
Update: I tried to use GetXXX such as GetFloat or GetDecimal methods to get values directly to a float/decimal value. Unfortunately, all those methods seem having similar rounding issue. Only GetValue() and forcing to string will get the exactly same string value as it is in the database. I thought I could do the conversion to a float or decimal value on .Net side, but the Parse() fails in my case. I am not sure why the rounding happen in Parse(). As some suggested the value are there, and it may be VS debug, watch or log caused rounding. However, when I tried to put the float value to a text box, it is rounded to 2 digits after decimal point. It is really a frustrating issue.
I'm not sure how you're looking at that variable and seeing 12.34. If I do the following in LINQPad:
Single.Parse("12.339123")
I get 12.33912. And if I ask it to give me a string with the full round-trip precision:
Single.Parse("12.339123").ToString("r")
I get 12.3391228, which is as close to exactly 12.339123 as you're going to get with a mere single-precision floating-point value.
Conclusion: you're using an imprecise means to inspect the variable's value. The variable itself is almost certainly fine, and holds just as precise a value as floating-point will allow; it's just that the debugger tooltip, or watch window, or logging library, or whatever it is you're using to look at that value, is only showing you a handful of digits.
try this way:
string sValue = myReader.GetValue(0).ToString("F6");

Categories

Resources