we are upgrading our code from C++ to C# and in alot of place we are formating strings.
for exmaple we have something like that:
OurString.Format("amount = %0.2Lf", (long double)amount);
How to convert the %0.2Lf into C# format ?
i've tried the following code but it's not the same
string formatString = String.Format("amount = {0}", (long double)amount));
thx
Use format strings: http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
You probably want either N2 or F2, depending on whether to include the thousands separator. So,
string formatString = String.Format("amount = {0:F2}", amount);
Edit:
As an simple FYI, if you're constructing a string in a series of distinct steps, you might want to use the StringBuilder class, which has an AppendFormat() method that accepts the same formating options as string.Format():
var builder = new StringBuilder();
// ... Your code to build the first part of the string
builder.AppendFormat("amount = {0:F2}", amount);
// ... whatever else you need to add
builder.ToString(); // outputs your final/completed string.
Whether you use StringBuilder or not depends on how critical memory management and/or performance is to the application; strings in C# are immutable, so when you concat them you are actually creating a brand new string. You can read more here: http://msdn.microsoft.com/en-us/library/system.string.aspx#Immutability
As Tieson wrote, F2... Just remember that in C the default locale is the C locale. So for example 0.00, while in C# the default locale is the current locale of the user (here in Italy 0,00). So it would be better to do:
string formatString = String.Format(CultureInfo.InvariantLocale,
"amount = {0:F2}", amount);
if you want to always everywhere format your digits in the same manner. Remember that when I told "here in Italy" also means "if I take my Italian Windows 8 in the USA the default locale will be Italian for me."
Ah... and there aren't long doubles in C# (or in .NET, or in newer versions of VC++ for that reason). Only doubles.
I'll add that using a double (or a long double) for money is an antipattern in itself... There is the decimal type for it.
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations that require large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding. For example, the following code produces a result of 0.9999999999999999999999999999 instead of 1.
Related
I want to add a thousands separator to a double number but want to keep the decimal places as is i.e. dont want any rounding.
#,# is solving my problem of adding the thousand separator but how do I preserve the decimal places ? #,# strips off the part after ..
I cannot use any culture or something like that & the developer whose function I am calling has only given me a way of changing the format by passing as parameter strFormat.
I did check other posts & even the docs but somehow not able to figure this out.
string strFormat = "#,#";
string str = double.parse("912123456.1123465789").ToString(strFormat);
//Expected here 912,123,456.1123465789
//Actual Output 912,123,456
//912123456.123 should give 912,123,456.123
//912123456.1 should give 912,123,456.1
//912123456.1123465789 should give 912,123,456.1123465789
//912123456 should give 912,123,456
Well, after looking at the documentation on Microsoft, it would appear that there is no particular way to allow a floating point position in a number - all characters in a format string are character placeholders.
I would recommend that you either use a very nasty predetermined number of #s to set the width of the decimal position, or the slightly less (or possibly more, depending on your outlook) nasty option of reading all numbers into an array, determining the longest decimal position, then building a format of #s using the result.
At the end of the day, this is a single format string that you can put into place, test and ensure it works, then come back later and fix if you find a better alternative.
Also, this is one of those things where you could put the string into a configuration setting and change as and when you need to - far more flexible.
To be honest, this is a very slight thing to be worried about in the grand scheme of performance and writing a program.
Technically, Udi Y gets my vote!
If you know the max number of decimal places, e.g. 10, then use:
string strFormat = "#,#0.##########";
Update:
This max number is known.
According to Microsoft documentation a Double value has up to 15 decimal digits of precision (including both before and after the decimal point). More than 15 digits will be rounded.
So if you must invoke that method of 'double.parse' and can only send the format, this is the best you can do:
string strFormat = "#,#0.###############";
You can calculate the formatting dynamically for each number:
public static void Main()
{
var number = 1234.12312323123;
var format = GetNumberFormat(number);
Console.WriteLine(number.ToString(format));
}
public static string GetNumberFormat(double number)
{
var numberAsString = number.ToString();
var decimalPartSize = numberAsString.Substring(numberAsString.LastIndexOf('.') + 1).Length;
return $"N{decimalPartSize}";
}
So
number = 1234.12312323123
will give you 1,234.12312323123. Works for negative numbers as well. Also, as we work with strings, there won't be any rounding errors or precision artifacts.
I am currently formatting a double using the code:
myDouble.ToString("g4");
To get the first 4 decimal places. However I find this often switches over to scientific notation if the number is very large or very small. Is there an easy format string in C# to just have the first four decimal places, or zero if it is too small to be represented in that number of places?
For example, I would like:
1000 => 1000
0.1234567 => 0.1235
123456 => 123456 (Note: Not scientific notation)
0.000001234 => 0 (Note: Not scientific notation)
You can try like this:
0.1234567.ToString("0.####")
Also check Custom Numeric Format Strings
#
Replaces the "#" symbol with the corresponding digit if one is
present; otherwise, no digit appears in the result string.
Also as Jon as correctly pointed that it will round your number. See the note section
Rounding and Fixed-Point Format Strings
For fixed-point format strings
(that is, format strings that do not contain scientific notation
format characters), numbers are rounded to as many decimal places as
there are digit placeholders to the right of the decimal point.
Use the String.Format() method.
String.Format("{0:0.####}", 123.4567123); //output: 123.4567
Note: Num of #'s indicate the maximum number of digits after decimal that are required.
I agree with kjbartel comment.
I wanted exactly what the original question asked. But his question is slightly ambiguous.
The problem with ### format is it fills the slot if a digit can be represented or not.
So it does what the original question asks for some numbers but not others.
My basic need is, and it's a pretty common one, if the number is big I don't need to show decimal places. If the number is small I do want to show decimal places. Basically X number of significant digits.
The "Gn" Format will do significant digits, but it switches to scientific notation if you go over the number of digits. I don't want E notation, ever (same requirement as the question).
So I used fixed format ("Fn") but I calculate the width on the fly based on how "big" the number is.
var myFloatNumber = 123.4567;
var digits = (int) Math.Log10(myFloatNumber);
var maxDecimalplaces = 3;
var format = "F" + Math.Max(0,(maxDecimalplaces - digits));
I swear there was a way to do this in C++ (Visual Studio Flavor) in teh format statement or in C# and perhaps there is, but I can't find it.
So I came up with this. I could have converted to a string and measured length before decimal point as well. But converting it to a string twice felt wrong.
I have some float values I want to convert to a string, I want to keep the formatting the same when converting, i.e. 999.0000(float) -> 999.0000(String). My problem is when the values contain an arbitrary number of zeroes after the decimal point, as in the previous example, they are stripped away when converting to a string, so the result I actually end up with is 999.
I looked at the format specifiers for the toString() method on MSDN, the RoundTrip ('R') specifier looks like it will produce what I want, but it is only supported for Single, Double and BigInt variables. Is there a format specifier like this for float variables?? Or would it be easier to just convert the values to doubles?
UPDATE: Just for clarity, the reason why I want to keep the trailing zeroes is because I'm doing a comparison of decimal places, i.e. I'm comparing the number of digits after the decimal place between two values. So for example, 1.00 and 1.00000 have a different number of digits after the decimal point. I know it's a strange request, it's for work and the requirement is coming from on high.
UPDATE 2-3-11:
I was thinking about this too hard, I'm reading the numbers from a txt file and then parsing them as floats, I'm going to modify the program to check whether the string values are decimals or whole numbers. Sorry for wasting your time, although this was very insightful.
Use ToString() with this format:
12345.678901.ToString("0.0000"); // outputs 12345.6789
12345.0.ToString("0.0000"); // outputs 12345.0000
Put as much zero as necessary at the end of the format.
Firstly, as Etienne says, float in C# is Single. It is just the C# keyword for that data type.
So you can definitely do this:
float f = 13.5f;
string s = f.ToString("R");
Secondly, you have referred a couple of times to the number's "format"; numbers don't have formats, they only have values. Strings have formats. Which makes me wonder: what is this thing you have that has a format but is not a string? The closest thing I can think of would be decimal, which does maintain its own precision; however, calling simply decimal.ToString should have the effect you want in that case.
How about including some example code so we can see exactly what you're doing, and why it isn't achieving what you want?
You can pass a format string to the ToString method, like so:
ToString("N4"); // 4 decimal points Number
If you want to see more modifiers, take a look at MSDN - Standard Numeric Format Strings
In C#, floatĀ is an alias for System.Single (a bit like intis an alias for System.Int32).
Does anyone know of an elegant way to get the decimal part of a number only? In particular I am looking to get the exact number of places after the decimal point so that the number can be formatted appropriately. I was wondering if there is away to do this without any kind of string extraction using the culture specific decimal separator....
For example
98.0 would be formatted as 98
98.20 would be formatted as 98.2
98.2765 would be formatted as 98.2765 etc.
It it's only for formatting purposes, just calling ToString will do the trick, I guess?
double d = (double)5 / 4;
Console.WriteLine(d.ToString()); // prints 1.75
d = (double)7 / 2;
Console.WriteLine(d.ToString()); // prints 3.5
d = 7;
Console.WriteLine(d.ToString()); // prints 7
That will, of course, format the number according to the current culture (meaning that the decimal sign, thousand separators and such will vary).
Update
As Clement H points out in the comments; if we are dealing with great numbers, at some point d.ToString() will return a string with scientific formatting instead (such as "1E+16" instead of "10000000000000000"). One way to overcome this probem, and force the full number to be printed, is to use d.ToString("0.#"), which will also result in the same output for lower numbers as the code sample above produces.
You can get all of the relevant information from the Decimal.GetBits method assuming you really mean System.Decimal. (If you're talking about decimal formatting of a float/double, please clarify the question.)
Basically GetBits will return you 4 integers in an array.
You can use the scaling factor (the fourth integer, after masking out the sign) to indicate the number of decimal places, but you should be aware that it's not necessarily the number of significant decimal places. In particular, the decimal representations of 1 and 1.0 are different (the former is 1/1, the latter is 10/10).
Unfortunately, manipulating the 96 bit integer is going to require some fiddly arithmetic unless you can use .NET 4.0 and BigInteger.
To be honest, you'll get a simpler solution by using the built in formatting with CultureInfo.InvariantCulture and then finding everything to the right of "."
Just to expand on the point about getbits, this expression gets the scaling factor from a decimal called foo:
(decimal.GetBits(foo)[3] & 16711680)>>16
You could use the Int() function to get the whole number component, then subtract from the original.
One of the fun parts of multi-cultural programming is number formats.
Americans use 10,000.50
Germans use 10.000,50
French use 10 000,50
My first approach would be to take the string, parse it backwards until I encounter a separator and use this as my decimal separator. There is an obvious flaw with that: 10.000 would be interpreted as 10.
Another approach: if the string contains 2 different non-numeric characters, use the last one as the decimal separator and discard the others. If I only have one, check if it occurs more than once and discards it if it does. If it only appears once, check if it has 3 digits after it. If yes, discard it, otherwise, use it as decimal separator.
The obvious "best solution" would be to detect the User's culture or Browser, but that does not work if you have a Frenchman using an en-US Windows/Browser.
Does the .net Framework contain some mythical black magic floating point parser that is better than Double.(Try)Parse() in trying to auto-detect the number format?
I think the best you can do in this case is to take their input and then show them what you think they meant. If they disagree, show them the format you're expecting and get them to enter it again.
I don't know the ASP.NET side of the problem but .NET has a pretty powerful class: System.Globalization.CultureInfo. You can use the following code to parse a string containing a double value:
double d = double.Parse("100.20", CultureInfo.CurrentCulture);
// -- OR --
double d = double.Parse("100.20", CultureInfo.CurrentUICulture);
If ASP.NET somehow (i.e. using HTTP Request headers) passes current user's CultureInfo to either CultureInfo.CurrentCulture or CultureInfo.CurrentUICulture, these will work fine.
You can't please everyone. If I enter ten as 10.000, and someone enters ten thousand as 10.000, you cannot handle that without some knowledge of the culture of the input. Detect the culture somehow (browser, system setting - what is the use case? ASP? Internal app, or open to the world?), or provide an example of the expected formatting, and use the most lenient parser you can. Probably something like:
double d = Double.Parse("5,000.00", NumberStyles.Any, CultureInfo.InvariantCulture);
The difference between 12.345 in French and English is a factor of 1000. If you supply an expected range where max < 1000*min, you can easily guess.
Take for example the height of a person (including babies and children) in mm.
By using a range of 200-3000, an input of 1.800 or 1,800 can unambiguously be interpreted as 1 meter and 80 centimeters, whereas an input of 912.300 or 912,300 can unambiguously be interpreted as 91 centimeters and 2.3 millimeters.