Decimal rounding issues - c#

I have a scenario in which some variable values have decimal values, the values can have leading .0, .234, .124, .125, numbers like this, and so on. If the number has leading decimal and zero it should ignore and if a number has leading 3 or more numbers it should round off to two.
Let's say the code is as follows:
var anone = "23"
var antwo = "23.0"
var anthree = "23.467"
var anfour = "23.125"
In order to remove the leading decimal and zero I have used the following method:
var removingzero = antwo.Replace(".0", "");
// The result will be = 23
In order to round off and limit the number to two decimal points I have used the following method:
var convertodecimal = Decimal.Parse(anthree);
var roundtotwo = Math.Round(convertodecimal, 2);
// The result will be = 23.47
similarly in order to convert the last one I follow the same method:
var convertodecimal = Decimal.Parse(anfour);
var roundtotwo = Math.Round(convertodecimal, 2);
// The result will be = 23.12
// But the Result should be = 23.13
So, the problem is when I am trying to round off any number like the last example it does not do it, how can I fix it.

It sounds like your question is a long way of asking "How can I force rounding UP when a decimal number ends in 5?"
If that's the case, then you can use the overload of Math.Round that takes a MidpointRounding argument, and specify either MidpointRounding.AwayFromZero or MidpointRounding.ToPositiveInfinity.
The behavior of these is the same for positive numbers, but difference is seen with negative numbers, where -23.125 will round to -23.13 if AwayFromZero is specified, or -23.12 if ToPositiveInfinity is specified.
So your code might look like this instead:
var roundtotwo = Math.Round(convertodecimal, 2, MidpointRounding.AwayFromZero);

Try by changing your Math.Round() to below one:
Math.Round(num,2, MidpointRounding.AwayFromZero)

Related

c# large fractional decimal split

My Requirement is Fractional Amount FIrst 2 decimal part add customer bank account and others fractional part add in dispute wallet account .
var amount = 40.235667745465465
I want to convert it 2 different variable
var customerBalance = // ??? - should be 40.23
var disputeBalance = amount - customerBalance
How can I do calculate the step marked ??? ?
This will work fine.
var firstAmount = Math.Floor(amount / 0.01) / 100 ;
var secondVariable = amount - firstAmount;
You probably want:
var firstAmount = Math.Round(amount, 2);
but note that this can round up as well as down; you may want to check whether secondVariable comes out negative, and if so: compensate.
Another way to look at it is to multiply by 100 and take the integer/decimal parts (hint: Math.Floor), then divide by 100 again.
If you are looking for a string, then it can be:
string secondVariableAsString = string.Format("{0:0.00}", secondVariable);
Another is:
Math.Truncate(100 * secondVariable) / 100;
However, this will cause overflow for large numbers.

Floor behavior with number 1.9999999999999999d [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 5 years ago.
Look at this situation:
var number1 = Math.Floor(1.9999999999999998d); // the result is 1
var number2 = Math.Floor(1.9999999999999999d); // the result is 2
In a both cases, the result should be 1. I know it's a very unlikely scenario, but possible to occur. The same ocurr with Math.Truncate method and (int) cast.
Why does it happen?
There is no exact double representation for a lot of numbers.
The double number the nearest from 1.9999999999999999 is 2, so the compiler rounds it up.
Try to print it before using your Math.Floor function !
However, the nearest from 1.9999999999999998 is still 1.something, so Floor gives out 1 .
Again, it would be enough to print the number before the function Floorto see that they were actually not anymore the one entered in the code.
EDIT : To print out the number with most precision :
double a1 = 1.9999999999999998;
Console.WriteLine(a1.ToString("G17"));
// output : 1.9999999999999998
double a2 = 1.9999999999999999;
Console.WriteLine(a2.ToString("G17"));
// output : 2
Since double precision is not always precise to 17 significative digits (including the first one before the decimal point), default ToString() will round it up to 16 significant digits, thus, in this case, rounding it up to 2 as well, but only at runtime, not at compile time.
If you put literals values into another variables, then you see it why:
var a1 = 1.9999999999999998d; // a1 = 1.9999999999999998d
var number1 = Math.Floor(a1);
Console.WriteLine(number1); // 1
var a2 = 1.9999999999999999d; // a2 = 2
var number2 = Math.Floor(a2);
Console.WriteLine(number2); // 2
As for why - this has to be something to do with precision of double and decision of compiler as to what value to use for a given literal.

How can I force a number to have 3 digits while keeping ALL decimal places?

In c#, I want to force 0s when converting from double to string in case a number is lower than 100, the only challenge is that I want to keep all decimal places. Examples
58.3434454545 = 058.3434454545
8.343 = 008.343
I tried with ToString + a format provider but I'm not certain what's the correct provider for keeping all decimal places
You can use formatter strings for .ToString(), documented here.
To do what you want you can use this as example, noting the maximum digits for double is 17:
double numberA = 58.3434454545;
numberA.ToString("000.##############"); //058.3434454545
double numberB = 8.343;
numberB.ToString("000.##############"); //008.343
This is a rather ass ugly solution but if you wanted the number of decimals to be dynamic you could try something like this:
private string FormatDouble(double dbl)
{
int count = BitConverter.GetBytes(decimal.GetBits((decimal)dbl)[3])[2];
var fmt = string.Concat("000.", new string('#', count));
return dbl.ToString(fmt);
}
Call it like this:
Console.WriteLine(FormatDouble(58.3434454545123123));
Console.WriteLine(FormatDouble(8.3431312323));
And your output would be this:
058.3434454545123
008.3431312323
I'm sure there is a much better way to do this and I'm not sure about performance, but hey it works and you don't have to guess the number of decimals you need, so that's a plus

Round off in listview

I am trying to round off each row to the nearest 1.0 in a column of a listview, so meaning 1.58 should show 2.00 and 1.48 should be 1.00 -
Math.Round(listView1.Columns[2].ToString(), 10);
You need to use 0 in digits parameter. You expect no digits here, but you're passing 10 to digit parameter which says to round with 10 digits after decimal.
var res = Math.Round(1.58, 0);//2
var res = Math.Round(1.48, 0);//1
Just saw you try to Round the string, You'll have to convert it to Double or decimal or whatever.
var rounded = Math.Round(Double.Parse(listView1.Columns[2].ToString()), 0);
In case you want to get String as a final result (as far as you've put ToString() in your code), you may just use appropriate formatting string ("F0" in your case):
String result = (1.58).ToString("F0"); // <- "2"
...
String result = (1.48).ToString("F0"); // <- "1"
You can't round a string directly.
string val=listView1.Columns[2].ToString();
double i;
if(Double.TryParse(val, out i))
{
Console.WriteLine(Math.Round(i)); // you can use Math.Round without second
// argument if you need rounding to the
// nearest unit
}

Can you compare two numbers stored as strings without knowing the datatype they represent?

If I have two numbers represented as strings, "100" and "200", "100.1" and "200.1", how can I compare them to see if they which one is bigger?
Is there a generic Number.Compare(stringA, stringB) that will take care of datatype? I am using a database entry to determine validation rules, but the values could be long, decimal, floats, etc, so I can't create a single one.
Easy with linq
var numbers = new string[] { "100" ,"200", "100.1" , "200.1" };
double max = numbers.Max(n => double.Parse(n));
Another solution with just string manipulation
int N = 100;
var max = numbers.Select(n => n.Split('.'))
.OrderByDescending(p => p[0].PadLeft(N,'0'))
.ThenByDescending(p => p.Length > 1 ? p[1].PadRight(N, '0') : "")
.Select(p => p.Length > 1 ? p[0] + "." + p[1] : p[0])
.First();
This will also work if you declared the type as decimal even if the numbers do not have a decimal point just as if one had a decimal point this will work as well
var strNumbers = new string[]
{
"100",
"200",
"100.1",
"200.1"
};
decimal maxVal = numbers.Max(m => decimal.Parse(m));
Is there a generic Number.Compare(stringA, stringB) that will take
care of datatype?
No, there is no generic number comparison. You should know type of number. E.g. you can't parse string with floating point number "100.1" as integer. I'd go with parsing your strings as decimals or doubles (which will handle both "100" and "100.1"), and then comparing results. Use Math.Max to get larger from two numbers:
var max = Math.Max(Double.Parse("100.1"), Double.Parse("200"));
Any number represented as a string should be convertable to a double.
You parse them. Either with an already existing parser, or manually, and the later MAY BE TRICKY because yo ustand up and tell me the formatting may be everthing, which could be scientific notation.
use int.tryParse because this will ensure that if the string is not a number it will not blow up

Categories