In MSDN documentation they say the "D" (or "d") format specifier is both for decimal numbers and dates but in fact it only formats a date (see this question also):
string.Format("{0:d}", DateTime.Now) // Works
string.Format("{0:d}", 12.998m) // Exception
So, why is that and when is it possible to use it to format a decimal?
The docs you linked to are pretty clear on this point - D is only supported by integral types
The "D" (or decimal) format specifier converts a number to a string of decimal digits (0-9), prefixed by a minus sign if the number is negative. This format is supported only for integral types.
Source: https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#DFormatString
Related
I am trying converting decimal to string which are in this format 0.85 to 85% by using below code, but i am always getting like this
85.00 %
and the code i am using like this below
item.ModifiedObject.Diversity.ToString("p", CultureInfo.CurrentCulture);
I am not sure where i am doing wrong, here i need to remove decimal places and at the same time i need to keep percent symbol with this.
Could any one suggest any suggestion on this that would be great full to me.
PS: I do not want to use split() function with respect to value
It's always useful to look at the documentation first, so let's visit it
The Percent ("P") Format Specifier
The percent ("P") format specifier multiplies a number by 100 and
converts it to a string that represents a percentage. The precision
specifier indicates the desired number of decimal places. If the
precision specifier is omitted, the default numeric precision supplied
by the current PercentDecimalDigits property is used.
Eg
decimal d = 1.23M;
Console.WriteLine(d.ToString("P0"));
Console.WriteLine(d.ToString("P1"));
Console.WriteLine(d.ToString("P2"));
or
decimal d = 1.23M;
Console.WriteLine($"{d:P0}");
Console.WriteLine($"{d:P1}");
Console.WriteLine($"{d:P2}");
Output
123%
123.0%
123.00%
I have this code:
string x = "-0.228469369833477";
Single s = Convert.ToSingle(x);
Console.WriteLine(s);
The console outputs: -2,284694E+14 .
What can I do to make it output: -0.228469369833477?
To output the number in its original form:
var s = -0.228469369833477;
Console.WriteLine(s.ToString("0.#######################"));
Note that s is likely a double, not a single. By using single you're very likely losing digits. To get enough precision to represent all of the digits, use Convert.ToDouble() instead.
To ensure that the number gets parsed properly in your locale, use CultureInfo.InvariantCulture, as other answers have stated.
A decimal will give you 28-29 significant digits of precision, with better precision and without the scientific notation problems.
Further Reading
Custom Numeric Format Strings
Single s = Single.Parse(x, CultureInfo.InvariantCulture);
If you want it to output that exact number, you can't use a float because it doesn't give you the precision you want. Try using a double.
double s = Double.Parse(x, CultureInfo.InvariantCulture);
Well, '.' is treated as a thousand separator (and ',' as decimal one) in your current culture (e.g. Russian Culture - "RU-ru" works like that) and since thousand separator ignored on conversion you have -228469369833477 (or -2,284694E+14).
string x = "-0.228469369833477";
// To ensure that '.' is treated as decimal separator
// lets put culture explicitly - CultureInfo.InvariantCulture
Single s = Convert.ToSingle(x, CultureInfo.InvariantCulture);
Console.WriteLine(s);
However, you have too many digits to represent for a Single and all you can return is -0.2284694 (not -0.228469369833477). If you want exact correspondence you have to use Double instead of Single:
Double s = Convert.ToDouble(x, CultureInfo.InvariantCulture);
// -0.228469369833477
Console.WriteLine(s, CultureInfo.InvariantCulture);
You can use
Console.WriteLine(string.Format("{0:N8}", s));
to output the single to 8 decimal places.
You can also specify the culture while doing the string formatting:
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0:N8}", s));
Here's a working fiddle: https://dotnetfiddle.net/nS9qXh
The ToString() of a double value, causes losing of the decimal places
(1521.6666666666667).ToString() ==> "1521.66666666667"
Is there any way to save all the decimal places when converting to string
Also
(1521.6666666666667).ToString("F13"); => "1521.6666666666700"
(1521.6666666666667).ToString("0.0000000000000"); => "1521.6666666666700
Does this have to do with size of the double value
The solution to this is reading the documentation. Seriously It is NOT "ToString" that is loosing it.
Let me quote the float data Type from https://msdn.microsoft.com/en-us/library/b1e65aza.aspx:
Precision: 7 digits.
The numbers are in your source, they are never in the float. Not properly. The value is rounded.
You have to format the string.
(1521.6666666666667).ToString("R");
decimal d = 1521.6666666666667M;
d.ToString();
According to the documentation:
Compared to floating-point types, the decimal type has more precision and a smaller range.
Specifically, decimal has 28-29 significant digits, rather than 15-16 for double.
You can use Decimal instead of Double:
(1521.6666666666667M).ToString(); // note "M"
Another possibility (if you have to use Double) is "R" format:
(1521.6666666666667).ToString("R");
Use The Round-trip ("R") Format Specifier, which will attempts to ensure that a numeric value that is converted to a string is parsed back into the same numeric value. This format is supported only for the Single, Double, and BigInteger types.
But for Double and Single values, the "R" format specifier in some cases fails to successfully round-trip the original value and also offers relatively poor performance. Instead, we recommend that you use the "G17" format specifier for Double values and the "G9" format specifier to successfully round-trip Single values.
From MSDN:
In some cases, Double values formatted with the "R" standard numeric format string do not successfully round-trip if compiled using the /platform:x64 or /platform:anycpu switches and run on 64-bit systems.
Resource: Standard Numeric Format Strings.
I have a question regarding the symbol that separates days from hours in TimeSpan.ToString output.
The standard TimeSpan format strings produce different separator symbols:
"c" produces a period (".") character
"g" and "G" produce a colon (":") character
Example:
// Constant format
Console.WriteLine(TimeSpan.FromDays(42).ToString("c", CultureInfo.InvariantCulture));
// Output: 42.00:00:00 (period character between days and hours)
// General short format
Console.WriteLine(TimeSpan.FromDays(42).ToString("g", CultureInfo.InvariantCulture));
// Output: 42:0:00:00 (colon character between days and hours)
// General long format
Console.WriteLine(TimeSpan.FromDays(42).ToString("G", CultureInfo.InvariantCulture));
// Output: 42:00:00:00.0000000 (colon character between days and hours)
Does anybody know what's the logic behind it?
However TimeSpan.Parse parses all of these string successfully.
These characters are hardcoded for those formats.
For "c" standard format
[-][d.]hh:mm:ss[.fffffff]
For "g" standard format
[-][d:]h:mm:ss[.FFFFFFF]
And for "G" Format Specifier
[-]d:hh:mm:ss.fffffff
Also doc says;
Unlike the "g" and "G" format specifiers, the "c" format specifier is
not culture-sensitive. It produces the string representation of a
TimeSpan value that is invariant and that is common to all previous
versions of the .NET Framework before the .NET Framework 4. "c" is the
default TimeSpan format string; the TimeSpan.ToString() method formats
a time interval value by using the "c" format string.
Also in Custom TimeSpan Format Strings
The .NET Framework does not define a grammar for separators in time
intervals. This means that the separators between days and hours,
hours and minutes, minutes and seconds, and seconds and fractions of a
second must all be treated as character literals in a format string.
Sounds like the most important reason is consistency between all .NET Framework versions. Maybe that's why they call this format as constant :)
There is more detail on MSDN - Standard TimeSpan Format Strings.
Essentially:
"c" is the Constant format: This specifier is not culture-sensitive. Format is [d’.’]hh’:’mm’:’ss[‘.’fffffff]
"g" is the General Short format: This is culture sensitive. Format is [-][d’:’]h’:’mm’:’ss[.FFFFFFF]
"G" is the General Long format: This is culture sensitive. Format is [-]d’:’hh’:’mm’:’ss.fffffff.
Look at the MSDN
The "g" TimeSpan format specifier returns the string representation of
a TimeSpan value in a compact form by including only the elements that
are necessary.
[-][d:]h:mm:ss[.FFFFFFF]
.....................
The "c" format specifier returns the string representation of a
TimeSpan value in the following form:
[-][d.]hh:mm:ss[.fffffff]
double Cost = 0.03;
var ttt = Cost.ToString("D3");
and
System.FormatException: Format specifier was invalid.
Why?
http://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#DFormatString
Says it's ok?
Take another look at your MSDN link, just a few sections higher up in the same document:
"D" or "d"
Decimal
Result: Integer digits with optional negative sign.
Supported by: Integral types only.
Precision specifier: Minimum number of digits.
Default precision specifier: Minimum number of digits required.
More information: The Decimal("D") Format Specifier.
1234 ("D") -> 1234
-1234 ("D6") -> -001234
(Emphasis mine)
If you want to ensure three digits to the left of decimal point (this is what 'D' does) with a floating-point type value, you will need to use a Custom Numeric Format String.
Cost.ToString("000.########");
But based on your comments, you really want it to the right of the decimal point, in which case the 'F' strings will work:
Cost.ToString("F3");
And if you're worried about the leading zero, you can do this:
Cost.ToString(".000");
based on your comment (4.4546 should be displayed as a string "4.455"), this should work:
var cost = 4.4546d;
var ttt = cost.ToString("0.000");
Probally 'Cost' is a floating point value. The "D" is a 'decimal' format specifier and doesn't works with floats.
Maybe what you need is in this article: http://msdn.microsoft.com/en-us/library/dd260048(v=vs.110).aspx