Exponents in C# - c#

int trail = 14;
double mean = 14.00000587000000;
double sd = 4.47307944700000;
double zscore = double.MinValue;
zscore = (trail - mean) / sd; //zscore at this point is exponent value -1.3122950464645662E-06
zscore = Math.Round(zscore, 14); //-1.31229505E-06
Math.Round() also keeps the exponent value. should zscore.ToString("F14") be used instead of Math.Round() function to convert it to non-exponent value? Please explain.

These are completely independant concerns.
Math.Round will actually return a new value, rounded to the specified decimal (ar at least, as near as one can do with floating point).
You can reuse this result value anywhere, and show it with 16 decimals precision if you want, but it's not supposed to be the same as the original one.
The fact that it is displayed with exponent notation or not has nothing to do with Round.
When you use ToString("F14") on a number, this is a display specification only, and does not modify the underlying value in any way. The underlying value might be a number that would or would not display as exponential notation otherwise, and may or may actually have 14 significant digits.
It simply forces the number to be displayed as a full decimal without exponent notation, with the number of digits specified. So it seems to be what you actually want.
Examples :
(executable online here : http://rextester.com/PZXDES55622)
double num = 0.00000123456789;
Console.WriteLine("original :");
Console.WriteLine(num.ToString());
Console.WriteLine(num.ToString("F6"));
Console.WriteLine(num.ToString("F10"));
Console.WriteLine(num.ToString("F14"));
Console.WriteLine("rounded to 6");
double rounded6 = Math.Round(num, 6);
Console.WriteLine(rounded6.ToString());
Console.WriteLine(rounded6.ToString("F6"));
Console.WriteLine(rounded6.ToString("F10"));
Console.WriteLine(rounded6.ToString("F14"));
Console.WriteLine("rounded to 10");
double rounded10 = Math.Round(num, 10);
Console.WriteLine(rounded10.ToString());
Console.WriteLine(rounded10.ToString("F6"));
Console.WriteLine(rounded10.ToString("F10"));
Console.WriteLine(rounded10.ToString("F14"));
will output:
original :
1,23456789E-06
0,000001
0,0000012346
0,00000123456789
rounded to 6
1E-06
0,000001
0,0000010000
0,00000100000000
rounded to 10
1,2346E-06
0,000001
0,0000012346
0,00000123460000

Related

Rounding amount up to 2 decimals based on the 3rd number after decimal

I Have to get amounts as below
1099948.275 = 1099948.27,
1099948.276 = 1099948.28,
1099948.274 = 1099948.27
when I use Math.Round(1_099_948.275, 2) I am getting output as 1099948.28 but not 1099948.27. I even tried with awayfromzero and toeven and none of them are working. Any idea?
Is there way to find 3rd number after decimal and if it is 5 just take first two number after decimal else go with mat.round?
This is not how rounding works, neither in C# nor in Math.
By default, anything 5 or more is rounded up, and anything less than 5 is rounded down. This is called "Away from Zero" rounding.
Rounding away from zero
Midpoint values are rounded to the next number away from zero. For example, 3.75 rounds to 3.8, 3.85 rounds to 3.9, -3.75 rounds to -3.8, and -3.85 rounds to -3.9. This form of rounding is represented by the MidpointRounding.AwayFromZero enumeration member.
The other mode is rounding to the closest even number. This is half of what you're looking for. In this way, when something ends with a "5" (the midpoint), that number is rounded to the closest even number, which could be up or down. This is done to distribute out the chances a rounding affects one particular party in a monetary transaction.
Rounding to nearest even, or banker's rounding
Midpoint values are rounded to the nearest even number. For example, both 3.75 and 3.85 round to 3.8, and both -3.75 and -3.85 round to -3.8. This form of rounding is represented by the MidpointRounding.ToEven enumeration member.
The source for both of the above quotes are on the Math.Round documentation page.
There is no supported rounding system that always rounds a 5 down. You'd need to inspect the value first to see if the last digit is a 5, then truncate the digit rather than attempt rounding.
One could implement your own rounding strategy:
public static double RoundDown(double value, int precision)
{
var rounded = Math.Ceiling(value * Math.Pow(10,precision) - 0.5) / Math.Pow(10,precision);
return rounded;
}
public static decimal RoundDown(decimal value, int precision)
{
decimal scale = 1;
for(int i=0;i<precision;i++)
{
scale *= 10;
}
var rounded = Math.Ceiling(value * scale - 0.5M) / scale;
return rounded;
}
Usage:
var values = new double[] {1099948.275, 1099948.276, 1099948.274 };
Console.WriteLine("double:");
foreach(var value in values)
{
var rounded = RoundDown(value, 2);
Console.WriteLine($"{value} = {rounded}");
}
Console.WriteLine("decimal:");
var values_m = new decimal[] {1099948.275M, 1099948.276M, 1099948.274M };
foreach(var value in values_m)
{
var rounded = RoundDown(value, 2);
Console.WriteLine($"{value} = {rounded}");
}
double:
1099948.275 = 1099948.27
1099948.276 = 1099948.28
1099948.274 = 1099948.27
decimal:
1099948.275 = 1099948.27
1099948.276 = 1099948.28
1099948.274 = 1099948.27
You can get what you need by subtracting 0.001 from the number before rounding it
Math.Round(1099948.275-0.001,2)
Edit:
to answer some of the comments
Math.Round(1099948.270-0.001,2) will still give the correct answer which is 1099948.27
similarly for any other number.
negative numbers may need to be handled differently depending on requirements.

C# Math.Round very long double - not working

here is what I'm trying to do:
double result = Math.Pow((1 + 8), 60) - 1;
And the result variable is:
1.7970102999144311E+57 double
And trying to:
Math.Round(result, 5);
Returns same : 1.7970102999144311E+57 double
I'd like to round it to 1.79701 for example
Any solutions ?
You're misunderstanding what you're seeing.
1.7970102999144311E+57
Is scientific notation for
1797010299914431100000... (with 41 trailing zeros).
It is a whole number, thus rounding it to 5 decimal places will correctly return the same value.
What you want to do is format the output of the number
String.Format(CultureInfo.InvariantCulture, "{0:0.#####E+0}", result);
Which returns 1.79701E+57. Note that this is a very different number from 1.79701
The problem you're having is that Math.Round rounds things to the right of the decimal point. For example if you're dealing with currency and you perform an operation that leaves you with $1.5234524, you would use:
Math.Round(1.5234524,2);
// output 1.52
The number you're dealing with is actually scientific notation for a very large number with nothing to the right of the decimal point. This is why the result of Math.Round is the same as the input.
The earlier comments and answers are correct. But to get what you are trying to achieve you can use the following:
double result = Math.Pow((1 + 8), 60) - 1;
string s = String.Format("{0:E5}", result);
double d = Double.Parse(s);

Multiplication error on double variable [duplicate]

I have this test code:
class Test
{
static void Main()
{
decimal m = 1M / 6M;
double d = 1.0 / 6.0;
decimal notQuiteWholeM = m + m + m + m + m + m; // 1.0000000000000000000000000002M
double notQuiteWholeD = d + d + d + d + d + d; // 0.99999999999999989
Console.WriteLine(notQuiteWholeM); // Prints: 1.0000000000000000000000000002
Console.WriteLine(notQuiteWholeD); // Prints: 1.
Console.WriteLine(notQuiteWholeM == 1M); // False
Console.WriteLine(notQuiteWholeD < 1.0); // Prints: True. Why?
Console.ReadKey();
}
}
Why this line prints 1?
Console.WriteLine(notQuiteWholeD); // Prints: 1
an this one, why prints True?
Is there an automatically rounding process? What can I do to print the correct/calculated value?
[Note: I found this example code in C# 5.0 in a Nutsheel page 30: Real Number Rounding Error].
Thanks in advance.
Not quite reading your question in the same way as the other two answers. The gist of it: Does the formatted string representation of a double "round" in C#?
Yes.
Internally double is represented with full IEEE-754 decimal digit precision (15-17 digits), which is why:
notQuiteWholeD < 1.0 == true // because notQuiteWholeD = 0.99999999999999989
However, when formatting it as a string, by default it will use 15 digit precision - equivalent to:
String.Format("{0:G15}", notQuiteWholeD) // outputs "1"
To get all the digits of the full internal representation, you can use:
Console.WriteLine("{0:G17}", notQuiteWholeD);
Or:
Console.WriteLine("{0:R}", notQuiteWholeD);
Both, in this case, will output "0,99999999999999989".
The former will always use 17 digit precision. The latter ("roundtrip precision") will use 15 digits if that's enough precision for the following to be true, otherwise it will use 17:
Double.Parse(String.Format("{0:G15}", notQuiteWholeD)) == notQuiteWholeD
Bonus Example:
... of when G17 and R differ:
Console.WriteLine("{0:G17}", 1.0000000000000699); // outputs "1.0000000000000699"
Console.WriteLine("{0:R}", 1.0000000000000699); // outputs "1.00000000000007"
1.0000000000000699 (17 significant digits) can be represented accurately enough for a roundtrip using only 15 significant digits. In other words, the double representation of 1.00...07 is the same as for 1.00...0699.
So 1.00...07 (15 digits) is a shorter input to get the exact same internal (17 digit) representation. That means R will round it to 15 digits, while G17 will keep all the digits of the internal representation.
Maybe it's clearer when realizing that this:
Console.WriteLine("{0:G17}", 1.00000000000007); // outputs "1.0000000000000699"
Console.WriteLine("{0:R}", 1.00000000000007); // outputs "1.00000000000007"
... gives the exact same results.
Decimal is stored in terms of base 10. Double is stored in terms of base 2. Neither of those bases can exactly represent 1 / 6 with a finite representation.
That explains all the output except Console.WriteLine(notQuiteWholeD). You get "1" for output, even though the actual value stored is less than 1. Since the output is in base 10, it has to convert from base 2. Part of the conversion includes rounding.
As we know, 1/6 = 0.1666 (repeating), decimal and double can not represent repeating numbers, they are calculated when assigned to. Since they are built from different backing data structures they represent a different set of possible numbers and round differently in some cases.
For this code:
Console.WriteLine(notQuiteWholeD < 1.0); // Prints: True. Why?
Since notQuiteWholeD is 0.99999999999999989 it prints true.
I'm not going to cover how the double and decimal work behind the scenes but here is some reading material if you're interested.
Double-precision floating-point format
SO - Behind the scenes, what's happening with decimal value type in C#/.NET?
Decimal floating point in .NET

Format a double to two digits after the comma without rounding up or down

I have been searching forever and I simply cannot find the answer, none of them will work properly.
I want to turn a double like 0.33333333333 into 0,33 or 0.6666666666 into 0,66
Number like 0.9999999999 should become 1 though.
I tried various methods like
value.ToString("##.##", System.Globalization.CultureInfo.InvariantCulture)
It just returns garbage or rounds the number wrongly.
Any help please?
Basically every number is divided by 9, then it needs to be displayed with 2 decimal places without any rounding.
I have found a nice function that seems to work well with numbers up to 9.999999999
Beyond that it starts to lose one decimal number. With a number like 200.33333333333
its going to just display 200 instead of 200,33. Any fix for that guys?
Here it is:
string Truncate(double value, int precision)
{
string result = value.ToString();
int dot = result.IndexOf(',');
if (dot < 0)
{
return result;
}
int newLength = dot + precision + 1;
if (newLength == dot + 1)
{
newLength--;
}
if (newLength > result.Length)
{
newLength = result.Length;
}
return result.Substring(0, newLength);
}
Have you tried
Math.Round(0.33333333333, 2);
Update*
If you don't want the decimal rounded another thing you can do is change the double to a string and then get get a substring to two decimal places and convert it back to a double.
doubleString = double.toString();
if(doubleString.IndexOf(',') > -1)
{
doubleString = doubleString.Substring(0,doubleString.IndexOf(',')+3);
}
double = Convert.ToDouble(doubleString);
You can use a if statement to check for .99 and change it to 1 for that case.
Math.Truncate(value * 100)/100
Although I make no guarantees about how the division will affect the floating point number. Decimal numbers can often not be represented exactly in floating point, because they are stored as base 2, not base 10, so if you want to guarantee reliability, use a decimal, not a double.
Math.Round((decimal)number, 2)
Casting to a decimal first will avoid the precision issues discussed on the documentation page.
Math.Floor effectively drops anything after the decimal point. If you want to save two digits, do the glitch operation - multiply then divide:
Math.Floor(100 * number) / 100
This is faster and safer than doing a culture-dependent search for a comma in a double-converted-to-string, as accepted answer suggests.
you can try one from below.there are many way for this.
1.
value=Math.Round(123.4567, 2, MidpointRounding.AwayFromZero) //"123.46"
2.
inputvalue=Math.Round(123.4567, 2) //"123.46"
3.
String.Format("{0:0.00}", 123.4567); // "123.46"
4.
string.Format("{0:F2}", 123.456789); //123.46
string.Format("{0:F3}", 123.456789); //123.457
string.Format("{0:F4}", 123.456789); //123.4568

Fix numbers count after point for decimal

How I can fix digits count after point for decimal type WITHOUT ROUNDING
in C#.
For example:
decimal coords = 47.483749999999816; (part of geographic coordinates)
I need to stay only 6 digits after point: 47.483749
You might use
decimal truncated = Math.Truncate(coords * 1000000m) / 1000000m;
or maybe
decimal truncated = Math.Truncate(coords / 0.000001m) * 0.000001m;
Of these two, I have come to prefer the latter. The number 0.000001m is represented internally as the mantissa 1 together with the scale 6, so dividing and multiplying by it is effectively just a move of the decimal point by six places.
The method where you multiply by 0.000001m in the end tends to give a result with exactly six digits after the decimal point, even with trailing zeroes if necessary. For example coords = 1.23m will lead to truncated being 1.230000m.
As noted in the comments, the above techniques will both lead to an OverflowException if coords is too huge (more than one millionth of the decimal.MaxValue).
For completeness, here are a couple of other solutions:
decimal truncated = coords - coords % 0.000001m;
This seems to work fine. The number of trailing zeroes will not always be correct though, but I believe it gives the same result wrt. the == operator (or decimal.Equals).
Finally, you can use:
decimal truncated = Math.Round(coords - 0.0000005m, 6, MidpointRounding.AwayFromZero);
but that works only for non-negative coords.
If what you really need is a formatted string, call a ToString overload on truncated. But beware, as I indicated, of trailing zeroes. If you use .ToString("F6") there should always be exactly six decimals.
Of course you can also use string manipulation for the truncating. It would go something like:
string coordsString = coords.ToString(CultureInfo.InvariantCulture);
int idxOfPoint = coordsString.IndexOf(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator);
if (idxOfPoint != -1 && coordsString.Length > 6 + 1 + idxOfPoint)
coordsString = coordsString.Remove(6 + 1 + idxOfPoint);
// coordsString is now truncated correctly.
// If you need a decimal, use decimal.Parse(coordsString)
Very tricky, and not suggested, but I don't really know what solution are you looking for (since you're avoiding rounding):
double k = 47.483749999999816;
k = double.Parse(Regex.Replace(k.ToString(), #"(\d+\.\d{6})(.\d+)", x => x.Groups[1].Value));
Console.WriteLine(k);
that prints
47.483749
You can use
decimal.Round( 47.483749999999816, 6)

Categories