string.format() not showing values - c#

Can anyone tell me why does this string.Format() doesn't show the 1st value?
long countLoop = 0;
long countTotal = 3721;
string.Format("Processed {0:#,###,###} lines of {1:#,###,###} ({2:P0})", countLoop, countTotal, ((double)countLoop / countTotal));
The result I got are
Processed lines of 3,721 (0 %)
But if I replaced countTotal with a number 1
string.Format("Processed {0:#,###,###} lines of {1:#,###,###} ({2:P0})", 1, countTotal, ((double)countLoop / countTotal));
I get this
Processed 1 lines of 3,721 (0 %).
Is there something about string.Format that I don't know about?

See the documentation on the the "#" custom format specifier:
Note that this specifier never displays a zero that is not a significant digit, even if zero is the only digit in the string.
If you'd like to display "0" in this case, take a look at the "0" custom format specifier:
If the value that is being formatted has a digit in the position where the zero appears in the format string, that digit is copied to the result string; otherwise, a zero appears in the result string.
This should work for you:
string.Format(
"Processed {0:#,###,##0} lines of {1:#,###,###} ({2:P0})",
countLoop, countTotal, ((double)countLoop / countTotal));

Change your string format to
string.Format("Processed {0:#,###,##0} lines of {1:#,###,###} ({2:P0})", countLoop, countTotal, ((double)countLoop / countTotal));
this will print 0 when the countLoop is zero.
As other have said before me, the # placeholder doesn't print the zero when it is not a significant digit.
Note I have fixed your indexing inside the format string.
You have only three parameters, so the index goes from 0 to 2 (not 3 as you have at the end ({3:P0})

Related

Error localising decimals with "," and "."

I want a price to be a decimal and for the decimal-sign to be localised. Depending on culture, a decimal may use , or ..
For now I am doing this:
subItem.price.ToString("#.#", CultureInfo.InvariantCulture);
But if the price is 0 (with no decimal point), the result of that turns out to be "" and that makes my system crash.
Is there a better pattern than "#.#" that might handle the 0 in a better way?
How about using "0" custom format specifier instead?
Console.WriteLine((0).ToString("0.0", CultureInfo.InvariantCulture));
prints
0.0
Your code returns empty string because from The "#" custom format specifier
Replaces the "#" symbol with the corresponding digit if one is
present; otherwise, no digit appears in the result string.
Note that this specifier never displays a zero that is not a
significant digit, even if zero is the only digit in the string. It
will display zero only if it is a significant digit in the number that
is being displayed.
By the way your title and your question says different things. Your question doesn't relevant with what number decimal separator is used when you format your value. It is all about why you get empty string when you format your 0 value.
Try 0.#. Will display 0 if value is 0.0
Possibly try using:
subItem.price.ToString("{0:C}", CultureInfo.InvariantCulture);
it formats your string as a currency.

How to parse an 0 decimal to String?

Why is it when I'm parsing a decimal (0) ToString my string shows as empty when using the method:
String somthing = someDecimal.ToString("#")
And when I'm using:
String somthing = somDecimal.ToString("0.##")
The string shows up as 0?
When I'm looking at the value in the debug mode in both way it's says they have a "0" in them.
From The "#" Custom Specifier
Note that this specifier never displays a zero that is not a
significant digit, even if zero is the only digit in the string. It
will display zero only if it is a significant digit in the number that
is being displayed.
If you want to display digits after your decimal point, you need to use 0.00 instead of 0.##.
Because pound "#" means convert to symbol if there is a number. 0 is an "empty" number, so it converts to "".
In fact, in second case, you get 0, as you imply to show at least one digit before dot.
This all is by design convention of C# language.
MSDN: the "#" Custom Specifier
The "#" custom format specifier serves as a digit-placeholder symbol.
If the value that is being formatted has a digit in the position where
the "#" symbol appears in the format string, that digit is copied to
the result string. Otherwise, nothing is stored in that position in
the result string. Note that this specifier never displays a zero that
is not a significant digit, even if zero is the only digit in the
string. It will display zero only if it is a significant digit in the
number that is being displayed.
So if the decimal would be 1 instead of 0 it would be diplayed even with ToString("#").
If you want a fixed number of decimals after the decimal point, you need to use
String somthing = somDecimal.ToString("0.00")
In your example you use the # specifier which means 'put here a number if there is a meaningful number'.
It would work if someDecimal is 0.01
decimal somDecimal = 0.01m
String somthing = somDecimal.ToString("0.##");
but not if
decimal somDecimal = 0.01m
String somthing = somDecimal.ToString("0.#");

Why does 0.ToString("#.##") return an empty string instead of 0.00 or at least 0?

Why does 0.ToString("#.##") return an empty string? Shouldn't it be 0.00 or at least 0?
# in the string format indicate that the value is optional. If you wish to get the output 0.00 you need the following:
0.ToString("0.00");
See here for the custom numeric formats that can be passed to this method.
Because in a format string, the # is used to signify an optional character placeholder; it's only used if needed to represent the number.
If you do this instead: 0.ToString("0.##"); you get: 0
Interestingly, if you do this: 0.ToString("#.0#"); you get: .0
If you want all three digits: 0.ToString("0.00"); produces: 0.00
From the comments to this answer, your argument seems to be,
it should show '0', because why would anyone ever want to see an empty string if the numeric value is 0?
The response is simple: You have the choice how you wish it to be displayed. That's what the custom format strings are for. You have simply chosen the incorrect format string for your needs.
According to the documentation about the Digit Placeholder.
If the value being formatted has a digit in the position where the '#' appears in the format string, then that digit is copied to the result string. Otherwise, nothing is
stored in that position in the result string. This specifier never displays the '0' character if it is not a significant digit, even if '0' is the only digit in the string. It will
display the '0' character if it is a significant digit in the number being displayed. The "##" format string causes the value to be rounded to the nearest digit preceding
the decimal, where rounding away from zero is always used. For example, formatting 34.5 with "##" would result in the value 35.
If you want the zero to display use the Zero PlaceHolder
f the value being formatted has a digit in the position where the '0' appears in the format string, then that digit is copied to the result string. The position of the
leftmost '0' before the decimal point and the rightmost '0' after the decimal point determines the range of digits that are always present in the result string.
The "00" specifier causes the value to be rounded to the nearest digit preceding the decimal, where rounding away from zero is always used. For example, formatting
34.5 with "00" would result in the value 35.
Try this 0.ToString("#,##; #,##;0")
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings#SectionSeparator
The first section applies to positive values, the second section applies to negative values, and the third section applies to zeros.
Use it like this:
0.ToString("#0.##")
0 after # will ensure to set output value to 0 if the value is 0 else it will display the value.
So 0.0.ToString("#0.##")=0.00 and 10.ToString("#.##")=10.00

Custom string formatting: ToString("00")

Given the following code:
string istanbul = "523";
Convert.ToInt32(istanbul.ToString("00"));
what does it return?
The "0" custom format specifier serves as a zero-placeholder symbol. If the value that is being formatted has a digit in the position where the zero appears in the format string, that digit is copied to the result string; otherwise, a zero appears in the result string. The position of the leftmost zero before the decimal point and the rightmost zero after the decimal point determines the range of digits that are always present in the result string.
The "00" specifier causes the value to be rounded to the nearest digit preceding the decimal, where rounding away from zero is always used. For example, formatting 34.5 with "00" would result in the value 35.
The "0" Custom Specifier
link text
This will not even compile:
string istanbul = 523
You cannot assign a number to a string variable like that. You also did not terminate the statement properly with a ;.
C# is also case sensitive, so istanbul and Istanbul refer to different variables.
To answer the question:
523.ToString("00"); // This will evaluate to the string "523"
Convert.ToInt32("523"); // This will evaluate to the integer 523
Read about custom numeric formatting strings.

Custom numeric format string to always display the sign

Is there any way I can specify a standard or custom numeric format string to always output the sign, be it +ve or -ve (although what it should do for zero, I'm not sure!)
Yes, you can.
There is conditional formatting. See Conditional formatting in MSDN
eg:
string MyString = number.ToString("+0;-#");
Where each section separated by a semicolon represents positive and negative numbers
or:
string MyString = number.ToString("+#;-#;0");
if you don't want the zero to have a plus sign.
Beware, when using conditional formatting the negative value doesn't automatically get a sign. You need to do
string MyString = number.ToString("+#;-#;0");
You can also use format strings in string.Format(); the format string is separated from the index with a colon (':')
var f = string.Format("{0}, Force sign {0:+#;-#;+0}, No sign for zero {0:+#;-#;0}", number);
For number { +1, -1, 0 } this gives:
1, Force sign +1, No sign for zero +1
-1, Force sign -1, No sign for zero -1
0, Force sign +0, No sign for zero 0
You can also use an interpolated string instead of string.Format to obtain the same result:
var f = $"{number}, Force sign {number:+#;-#;+0}, No sign for zero {number:+#;-#;0}";
Contrary to the other answers it seems that if you want to get +1, -1, +0 (for arguments 1, -1, 0) you need to use the format:
String.Format("{0:+#;-#;+0}", 0)); // output: +0
or
String.Format("{0:+0;-#}", 0)); // output: +0
If you use just +#;-# it will display just + (not +0) for 0.
The "#" Custom Specifier (at https://msdn.microsoft.com/en-us/library/0c899ak8.aspx)
Note that this specifier never displays a zero that is not a significant digit, even if zero is the only digit in the string. It will display zero only if it is a significant digit in the number that is being displayed.
Also please keep in mind that if you need any decimal precision you need to specify it like that:
String.Format("{0:+0.##;-#.##}", 0)); // output: +0
or, if you wan't zeros to always show up, like that:
String.Format("{0:+0.00;-#.00}", 0)); // output: +0.00
For a numeric expression of any type:
+###,###,###,###,###,###,###,###,###,##0.###,###,###,###,###,###,###,###,###,###;-###,###,###,###,###,###,###,###,###,##0.###,###,###,###,###,###,###,###,###,###;0
Use three parts for three cases: positive;negative;zero
Other aspects of the example:
Zero is not signed. You could have it show as anything, such as "zero".
Absolute values less than one have a leading 0 before the decimal point. Adjust to taste.
Number of digits is for the largest and smallest absolute decimal values. Adjust to taste.
Decimal point character is culture-specific. .NET substitutes.
Grouping separators are optional. The character is culture-specific. .NET substitutes. (The positions are also culture-specific but that's only controlled by your format string.) You also use any other character except the special characters for Format (which include , . # 0).
I cannot comment so i Do an answer here (nuts reputation system ....)
You can Use number.ToString("+0;-#") very well to Produce the UTC String TimeFormat
Here showed in PowerShell code
"$([System.DateTime]::Now.ToString('HH:mm:ss.fff'))$($([System.TimeZoneInfo]::Local.GetUtcOffset([System.DateTime]::Now).TotalMinutes.ToString('+0;-#')))"
Thank you #gcores https://stackoverflow.com/users/40256/gcores

Categories

Resources