i want to display a integer value with a thousand seperator. i found following ways:
int i = 0101010101;
Console.WriteLine(i.ToString("N0")); // 101.010.101
Console.WriteLine(i.ToString("#,#"));// 101.010.101
what's the difference / advantage of each?
There is at least one difference. If you test it with i = 0, then the "N0" format string outputs 0, and the "#,#" format string outputs nothing at all. As the documentation states:
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.
Related
In some legacy .NET code I've come across a number of custom numeric format strings like this:
###,##0.00
What is the difference between this and:
#,#0.00
?
EDIT:
Here are some example inputs I've tried, all of which yield the same result for both masks: 1000000, 1000, 100, 10, 1.456, -30000, 0.002.
EDIT:
#Sahuagin suggested that these masks could be the same because of how the culture is set to group to three digits. However, even using this I can't demonstrate a difference:
var culture = new CultureInfo("en-US");
culture.NumberFormat.NumberGroupSizes = new[] { 1, 2, 3, 4 };
culture.NumberFormat.NumberGroupSizes.Dump();
1234567890.ToString("#,#0.00", culture).Dump(); // 1234,567,89,0.00
1234567890.ToString("###,#0.00", culture).Dump(); // 1234,567,89,0.00
More generally, I understand that # is an "optional" digit which won't create leading or trailing zeroes. However, it seems like just a single # before the decimal point is enough to get all leading digits. The MSDN docs seem to differentiate between # and ## but the explanation doesn't make much sense to me and I haven't found an example where it makes a difference.
# indicates a place where a digit will appear, if one exists in the number. Absent any such symbols, leading digits automatically appear (though you must have at least either one # or one 0, or no number will appear), but they are still useful as placeholders in some kinds of formats, for example a telephone number:
var value = 1234567890;
Console.WriteLine("{0:###-###-####}", value);
// outputs 123-456-7890
In your example of #,#0.00, I think that only manages to still format correctly (with groups of three) because , is a special grouping symbol, and the culture info is set to group digits in threes. Without that, you would get something like 123-45.67, if you used a - instead of a , for example.
Here is more specific information about , from MSDN:
The "," character serves as both a group separator and a number scaling specifier.
Group separator: If one or more commas are specified between two digit placeholders (0 or #) that format the integral digits of a number, a group separator character is inserted between each number group in the integral part of the output.
The NumberGroupSeparator and NumberGroupSizes properties of the current NumberFormatInfo object determine the character used as the number group separator and the size of each number group. For example, if the string "#,#" and the invariant culture are used to format the number 1000, the output is "1,000".
Number scaling specifier: If one or more commas are specified immediately to the left of the explicit or implicit decimal point, the number to be formatted is divided by 1000 for each comma. For example, if the string "0,," is used to format the number 100 million, the output is "100".
So in your first example of ###,##0.00, it could probably be reduced to #,0.00, if desired, although #,##0.00 is what I usually use since it is much more clear.
I need to create a pattern for a "text" type input to only allow a number from 0 to a specific max value and at the same time and validate to a specific number of decimal places.
Quick example:
Max Value = 300.86
Max Decimal Places = 3
Valid inputs:
0
1
300
300.86
300.85
300.850
300.851
.2
0.3333
Invalid inputs:
-1
301
300.87
300.861
1,30.2
1,.0
,.1
Currently I only know how to validate number of decimal places using this pattern:
^[,0-9]*(.\d{1,{0}})?$
Note:
I can't use type=number because I can't use any pattern with that :(
please help
I think something like this, is what you're after:
^(300(?:\.(?:[0-7]\d{0,2}|8(?:[0-5]\d?|60?)?))?|[0-2]?\d{0,2}(?:\.\d{0,3})?)$
See it here at REGEX STORM.
(Had to tweak it there, to end in \r, because REGEX STORM wouldn't match $ with end of line even though multi-line was selected???)
Explanation
It has two parts. The latter [0-2]?\d{0,2}(?:\.\d{0,3})? test for numbers below 300. It optionally starts with 0, 1 or 2 ([0-2]?). Then any two digits can follow (\d{0,2}). Then, optionally, it's followed by a . which, if present, can be followed by up to three digits (decimals) ((?:\.\d{0,3})?).
The first part - 300(?:\.(?:[0-7]\d{0,2}|8(?:[0-5]\d?|60?)?))? - test for when the integer part is exactly 300. It may then optionally be followed by a decimal point, and one out of three cases:
[0-7]\d{0,2} a digit in the range 0 to 7, followed by up to two digits
8(?:[0-5]\d*|60*)? an 8 followed by a digit in the range 0 to 5, optionally followed by a digit (The [0-5]\d? alternation).
or the number 86 and an optionall 0 (the 60? alternation)
These parts are in a capturing group separated by an alternation - |. The whole expression must be at the start of the string (^) (or line with multi-line flag) and at the end of the same ($).
Edit
Done some tweaking 'cause some numbers wrongly failed.
Edit 2
Completely missed "the maximum number of decimals" part. Fixed. (Fooled by the "valid" example 0.3333)
I don't know anything about C# so I'll just have to assume that what I can do in Python, you can find some way to do in C#. I'll give you my suggestion in pseudocode (this is not meant to mirror Python).
maxValue = some number
nDecimals = some number
givenValue = text with some number to be tested
#split number on decimal; remove non-digit characters from each side
leftSideOfDecimal = Replace(pattern = '^(\d{1,3}(,\d{3})*)(\.\d*)$', replacement = '\1', givenValue)
leftSideOfDecimal = Replace(',', '', leftSideOfDecimal)
rightSideOfDecimal = Replace('^(\d{1,3}(,\d{3})*)(\.\d*)$', '\3', givenValue)
rightSideOfDecimal = Replace('\.','',rightSideOfDecimal)
leftSideOfDecimal = pass leftSideOfDecimal to function to change type from text to integer
if leftSideOfDecimal <= maxValue and numberOfCharacters(rightSideOfDecimal) == nDecimals:
do whatever you want
Alternatively, if you have a function by which you can split strings on a given character (like a decimal or comma), then you just split the input on the decimal, clean up the first side as in the code, and then proceed with the last three lines of the code above. That way would save you from having to use a mildly complicated regex.
Why 0.0.ToString(".####") returns empty string but not 0? What format string should I use for proper output?
To always show the digit for the 1s position, then you need to specify a zero in the string format specifier for that digit. See the following:
// outputs "0"
0.0.ToString("0.####")
If you want to show extra decimal places, even if they are zero, then you can also use zeros to do that:
// outputs "5.1000"
(5.1).ToString("0.0000")
For more information see:
Custom Numeric Format Strings
If you want to show only the 1s position for the number zero.. then do this:
String text = (number == 0) ? "0" : number.ToString(".####");
Think about what you're asking - you ask for no required digits before the decimal point and up to 4 optional significant digits after the decimal point.
Since 0.0 has no significant digits before or after the decimal, it returns nothing.
To give you the proper format string we need the expected output in each of the following cases:
A number >= 1
A number between 0 and 1 (exclusive)
0
Note that you can use section separators to explicitly say how you want to format positive numbers, negative numbers, and 0:
0.0.ToString(".####;-.####;0") // returns "0"
The nice thing about using section separators (versus explicitly checking for 0) is that it will use the "0" format specifier if the formatted string would be equivalent to 0.
For example,
(-0.0000001).ToString(".####;-.####;0")
will return "0" since the small negative number will be rounded to four decimals based on your format specification.
I'm converting code between delphi and c#.
Values are stored as strings in a text file from the delphi app. An example of the stored value is : '4.42615029219009E-5'
Now in my c# app I need to read in that string value and then later have the capability to write out the value again. Initially I used code similar to:
string stringField = "4.42615029219009E-5";
double someMoneyVar = Convert.ToDouble(stringField)
later if I need to recreate the text file with the value of someMoneyVar then using a simple:
string.Format("{0}", someMoneyVar)
would output:
4.42615029219009E-05 // note the 0
Lastly, I read that it is better to store money as decimals in c#. I've tried to convert the string value to a decimal using decimal.Parse(someMoneyVar, NumberStyles.Any) , however the formatting is lost.
I need the data to be output exactly as it was input.
Note, the value of someMoneyVar may not always contain an exponential part. e.g. 0.0428860331919443. If there is no exponential part to the value of someMoneyVar then the value is written correctly to the text file.
Update:
Digging into delphi's FloatToStr function and help files (which is what stores the value in the text file) i came with the following:
The resulting string uses fixed point format if the number of digits
to the left of the decimal point in the value is less than or equal
to the specified precision, and if the value is greater than or equal
to 0.00001 (Edit: this should be 0.0001. There is an error in the delphi documentation). Otherwise the resulting string uses scientific format,
and the Digits parameter specifies the minimum number of digits in
the exponent (between 0 and 4).
...
If the section for positive values is empty, or if the entire format
string is empty, the value is formatted using general floating-point
formatting with 15 significant digits, corresponding to a call to
FloatToStrF with the ffGeneral format. General floating-point
formatting is also used if the value has more than 18 digits to the
left of the decimal point and the format string does not specify
scientific notation.
So bearing in mind that the FloatToStr function does a call to FloatToStrF uses 15 significant (precision) digits and a 0 as the minumum number of digits hence we end up with
4.42615029219009E-5
if the digits was 2 then the number would be displayed as
4.42615029219009E-05
According to the MSDN http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx#GFormatString
using the general format specifier, the precision of double is 15 and decimal is 29
Fixed-point notation is used if the exponent that would result from
expressing the number in scientific notation is greater than -5 and
less than the precision specifier; otherwise, scientific notation is
used. The result contains a decimal point if required, and trailing
zeros after the decimal point are omitted. If the precision specifier
is present and the number of significant digits in the result exceeds
the specified precision, the excess trailing digits are removed by
rounding.
However, if the number is a Decimal and the precision specifier is
omitted, fixed-point notation is always used and trailing zeros are
preserved.
If scientific notation is used, the exponent in the result is prefixed
with "E" if the format specifier is "G", or "e" if the format
specifier is "g". The exponent contains a minimum of two digits. This
differs from the format for scientific notation that is produced by
the exponential format specifier, which includes a minimum of three
digits in the exponent.
The result string is affected by the formatting information of the
current NumberFormatInfo object. The following table lists the
NumberFormatInfo properties that control the formatting of the result
string.
One can easily set the precision e.g. mydecimal.toString("G15") however i still haven't found a way to set the number of digits after the 'E' sign as easily as in the delphi FloatToStrF function
To convert strings to numbers, as you already figured out, you just use a double.
I'd try a different conversion though:
double myNum = double.Parse("<yournumber>", NumberStyles.AllowExponent | NumberStyles.Float, CultureInfo.InvariantCulture);
AllowExponent and Float should keep the notation, and InvariantCulture takes care of the decimal divider (which might not be a dot depending on the locale).
You can output scientific notation numbers via string.Format(), like this:
double num = 1234.5678; // 1.2345678e+03
string.Format("{0:e}", num); // should output "1.2345678E+03"
If you have to distinguish between numbers with and without the "E+xx" part, you'll have to search for it before converting the string to double, and a full snippet (WARNING: not tested!) could look like:
string myString = ReadNumberFromFile(); // Just a placeholder method
double myNum = double.Parse(myString, NumberStyles.AllowExponent | NumberStyles.Float, CultureInfo.InvariantCulture);
string output = string.Empty; //this will be the "converted-back number" container
if (myString.IndexOf("e", StringComparison.OrdinalIgnoreCase) >= 0)
{
//Number contains the exponent
output = string.Format("{0:e}", num); // exponential notation 'xxxExx' casing of 'e' changes the casing of the 'e' in the string
}
else
{
//TODO: Number does NOT contain the exponent
output = string.Format("{0:f}", num); // fixed-point notation in the form 'xxxx.xxx'
}
The point here is that, as far as number go, being with or without an exponent doesn't make any difference whatsoever, it's just a matter of representation (and it makes little sense to distinguish between them: it's really the same thing).
I need for this to work in a single format statement and to work for both ints and decimals:
For example:
int myInt=0;
decimal myDecimal=0.0m;
// ... Some other code
string formattedResult1=String.Format("{0}",myInt);
string formattedResult2=String.Format("{0}",myDecimal);
The expected results are:
"" (i.e., string.Empty) if the item to be formatted is zero
and a numeric value (e.g., "123.456" for the decimal version) if it isn't.
I need for this to occur exclusively as a result of the format specification in the format string.
This should do:
string formattedResult1 = string.Format("{0:0.######;-0.######;\"\"}", myInt);
The colon introduces a numeric format string. The numeric format string is divided into 3 parts with semicolons: part 1 is for positive numbers, part 2 for negative numbers, and part 3 for zeros. To define a blank string you need to delimit it with double quotes otherwise it doesn't like it.
See MSDN for the full syntax.
based from the accepted answer above i have done the same thing in microsoft "report builder"
this worked for me (shows 2 decimal places, blank for zero) :
,##0.00;-#,##0.00;""