c# how to prevent double value truncation when converting to string - c#

Double x = 11.123456789123456;
string y = Convert.ToString(x);
//gives y=11.1234567891235
//y should be =11.123456789123456
From the above code how can I prevent the last digit(6) from being truncated

Use
string y = x.ToString("G17");
or
string y = x.ToString("R");
as written here:
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.
Note that not all the numbers can be represented exactly...
11.123456789123458.ToString("G17") == "11.123456789123457"

double is only precise up to 15-16 digits, try using decimal type
See Msdn
Decimal

The reason this is happening is because Double occupies 8 bytes and has precision of 15-16 digits.
Use Decimal instead
Decimal x = 11.123456789123456M;
string y = Convert.ToString(x);
//gives y=11.12345678912356
Refer this link, look for answer by cds333

Related

c# decimal keep only 2 decimals

I have a decimal number: 12.4465463455
decimal value = 12.4465463455m;
How can I round this decimal and remove extra decimals but 2 so the decimal will be 12.45 ? Please notice I don't need a string. I know how to convert this to a string with 2 decimals and rounded. But have no idea how to manipulate the decimal variable itself.
Just use Math.Round, so:
decimal value = 12.4465463455m;
decimal value2dp = Math.Round(value, 2); //2 => 2 decimal places

Wrong parsing from string to double

double value = double.Parse("4655.927411110702", CultureInfo.InvariantCulture);
Why this parsing is getting me result: 4655.9274111107025?
Somehow it adds to my number 5 at the end. How should I convert this string to double and have a correct result?
You can't. Not all numbers can be represented exactly in double precision floating point, and the closest such double to 4655.927411110702 is 4655.927411110702450969256460666656494140625, and the default formatting you're using trims off the majority of the "joke" digits.
C# does have a decimal type. Can you not use that?
decimal value = decimal.Parse("4655.927411110702", CultureInfo.InvariantCulture);

Format int to string with decimals

I am trying to format a string using string.Format method to produce a fixed decimal string from an int data type.
I have tried following code :
sOutputString = string.Format(
"Days:{0:D1} Hours:{1:D1} Minutes:{2:D1} Seconds:{3:D1} Miliseconds:{4:D1}",
objTimeCalculate.Days,
objTimeCalculate.Hours,
objTimeCalculate.Minutes,
objTimeCalculate.Seconds,
objTimeCalculate.Miliseconds);
The values of the properties Days, Hours, Minutes, Seconds are int data type and formatted using the D format specified. However I need decimal values produced in the string.
Output should be :
sOutputString = Days : double_value Hours : double_value Minutes : double_value Seconds : double_value Miliseconds : integer_value
Since the property days can go beyond reach of the integer datatypes reach.
Given that objTimeCalculate is a TimeSpan all those variables are int. Therefore they dont have a decimal value.
However we could use the format string F1 which will return with a fixed decimal value, however this will always be 0.
Example:
var objTimeCalculate =(DateTime.Now - DateTime.UtcNow);
var sOutputString = string.Format(
"Days:{0:F1} Hours:{1:F1} Minutes:{2:F1} Seconds:{3:F1} Miliseconds:{4:F1}",
objTimeCalculate.Days,
objTimeCalculate.Hours,
objTimeCalculate.Minutes,
objTimeCalculate.Seconds,
objTimeCalculate.Milliseconds);
Result:
Days:0.0 Hours:9.0 Minutes:29.0 Seconds:59.0 Miliseconds:996.0
You can consult Standard Numeric Format Strings for more details.
"F" or "f" Fixed-point
Result: Integral and decimal digits with optional negative sign.
Supported by: All numeric types. Precision specifier: Number of
decimal digits. Default precision specifier: Defined by
NumberFormatInfo.NumberDecimalDigits.
The Fixed-Point ("F") Format Specifier.
You are looking F specifier:
sOutputString = string.Format(
"Days:{0:F2} Hours:{1:F2} Minutes:{2:F2} Seconds:{3:F2} Miliseconds:{4:F2}",
objTimeCalculate.Days,
objTimeCalculate.Hours,
objTimeCalculate.Minutes,
objTimeCalculate.Seconds,
objTimeCalculate.Miliseconds);

How to display percentage with one decimal and manage culture with string.Format in C#?

I would like to display a percentage and manage the culture.
Like this : https://msdn.microsoft.com/fr-fr/library/system.globalization.numberformatinfo.percentnegativepattern%28v=vs.110%29.aspx
I do that :
double percentage = 0.239;
NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
string percentageValue = string.Format(nfi, "{0:P1}", percentage);
It works (for example result can be "%23,9" or "23,9 %")
But I don't want to display the decimal if not needed
=> "100 %" instead of "100,0 %".
I try with #.#, its works but I want to manage the current culture (decimal separator, percentage position, etc).
How can I achieve that ?
Thanks !
A period (.) in the format is actually a replaced character: the culture's decimal separator1. See here on MSDN.
So that part is easy.
However the P format's decimal places are based on details in the applicable locale, there is no custom formatting for "percent digits".
Additionally
But I don't want to display the decimal if not neede
is very hard for floating point values. As approximations any attempt at something like if (value.FractionalPart == 0) is doomed the underlying binary representation. For example 0.1 (10%) is not represented exactly and after multiplying by 100 (for the percentage display) is unlikely to be exactly 10. Thus "has no decimal places" will actually need to be "sufficiently close to an integral value":
var hasFraction = Math.Abs(value*100.0 - Math.Round(value*100, 0)) < closeEnough;
and then build the format string depending on the result.
1 Ie. if you want a period independent of culture you need to quote it – with single quotes – eg. value.ToString("#'.'##").
Standard Numeric Format Strings
"P" or "p" (Percent):
Result: Number multiplied by 100 and displayed with a percent symbol.
Supported by: All numeric types.
Precision specifier: Desired number of decimal places.
Default precision specifier: Defined by NumberFormatInfo.PercentDecimalDigits.
More information: The Percent ("P") Format Specifier.
1 ("P", en-US) -> 100.00 %
1 ("P", fr-FR) -> 100,00 %
-0.39678 ("P1", en-US) -> -39.7 %
-0.39678 ("P1", fr-FR) -> -39,7 %
NumberFormatInfo.PercentDecimalDigits contains this example:
NumberFormatInfo nfi = new CultureInfo( "en-US", false ).NumberFormat;
// Displays a negative value with the default number of decimal digits (2).
Double myInt = 0.1234;
Console.WriteLine( myInt.ToString( "P", nfi ) );
// Displays the same value with four decimal digits.
nfi.PercentDecimalDigits = 4;
Console.WriteLine( myInt.ToString( "P", nfi ) );
Which results in the output:
12.34 %
12.3400 %
Ok thanks, so that's not possible with string.Format()
And what do you think of this ?
bool hasDecimal = !percentage.Value.ToString("P1", CultureInfo.InvariantCulture).EndsWith(".0 %");
string percentageMask = hasDecimal ? "{0:P1}" : "{0:P0}";
string percentageValue = string.Format(CultureInfo.CurrentCulture, percentageMask, percentage);

Formatting a decimal value with ToString() to have commas as thousand separators where the amount of decimal places is unknown

I have many decimals, each rounded differently:
decimal quantity = Decimal.Round(item.Quantity.Value, 2,
MidpointRounding.AwayFromZero);
decimal difference = Decimal.Round(quantity * eva, 0,
MidpointRounding.AwayFromZero);
When binding to the UI, I convert to string like this:
string Quantity = quantity.ToString("G", CultureInfo.InvariantCulture);
string Difference = difference.ToString("G", CultureInfo.InvariantCulture);
Is there a generic way to insert commas for thousand separators while keeping the original decimal rounding the same?
Try using Format.
double d = 1.234567;
String output = d.ToString("#,##0.##");
Also,
double d = 123456789.1;
string format = d.ToString().
IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
>=0 ? "#,##0.00" : "#,##0";
Console.WriteLine (d.ToString(format));
For anyone wondering, I ended up using String.Format(new CultureInfo("en-US"), "{0:N}", difference) and changed the N depending on how many decimal places I needed.
You can use the "N" format specifier and supply the number of digits you want any number to retain. If you want each number to potentially have a different number of digits you wall have to determine the number to supply to the format string each time.
quantity.ToString("N(digits)");
Complete documentation is at http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx#NFormatString

Categories

Resources