Decimal and mathematical operations

I have a simple conversion of a decimal in C#. It looks like this:

private decimal BaseValue
{
    get; set;
}

public decimal ConvertedValue 
{
    get
    {
        return BaseValue * (365 / 360);
    }
}

However, this does not work. I assume because C# is processeing the numbers in the fraction as integers. So I can do like this instead (which works):

public decimal ConvertedValue 
{
    get
    {
        return BaseValue * (decimal)((double)365 / (double)360);
    }
}

Now this seems a bit like overkill, but I can live with that. My primary question is this:

Why does Visual Studio warn me that 'Cast is redundant', for the (double) cast? And if I remove the (double) cast, then the (decimal) cast becomes redundant. And if I remove that, then I am back to the solution, which does not work. Help...?

Answers


one way to solve this is by specifying that the numbers in the calculation are decimal with a m at the end

return BaseValue * (365m / 360m);

Why does Visual Studio warn me that 'Cast is redundant', for the (double) cast

because when you have a double on one side of the equation then the result will be a double.

(double)365 / (double)360

have a look at the documentation of the * operator overloads. You will see that the operands are always of the same type like:

decimal operator *(decimal x, decimal y);


... then the (decimal) cast becomes redundant.

again, because when you have a decimal on one side of the equation then the result will be a decimal:

BaseValue * (decimal)(365 / 360)

The problem here is the scope! you cast the entire result of the division to decimal . Actually you could solve your problem simply by removing the parentheses:

return BaseValue * 365 / 360;

this way you equation will be correct, because the result of the * multiplication will be a decimal (since one of the operands is a decimal, so the other will be casted implicitly) and again the result of the division will also be a decimal for the same reason.

NOTE: Removing the parentheses is in general not the same as leaving them in. In some cases, floating-point operations differ in the result when the order of such operations changes, even though the two expressions are mathematically identical. Comment by Banex

EDIT:

The m thingy is called a literal. More information for all type-suffixes or literals can be found on the documentation here


The decimal cast is redundant, because the compiler knows you want to return a decimal.

One of the two double casts is redundant, because when you cast one of the ints into a double, it's clear that you use the double division operator instead of integer division.

But it should be enough to just use the decimal literal suffix m:

return BaseValue * (365m / 360);

Again, one m is enough to infer the correct operator.


But hey, BaseValue already is decimal and the parenthesis don't make sense (if you don't want integer divivsion)... this should work, too:

return BaseValue * 365 / 360;

use the m suffix:

return 365m/360 * BaseValue;

There are some suffixes for some types of numbers, for example:

 // Use long suffix.
 long l1 = 10000L;

 // Use double suffix.
 double d1 = 123.764D;

 // Use float suffix.
 float f1 = 100.50F;

 // Use unsigned suffix.
 uint u1 = 1000U;

 // Use decimal suffix.
 decimal m2 = 4000.1234M;

 // Use unsigned suffix and long suffix.
 ulong u2 = 10002000300040005000UL;

Suffixes specify number types. They instruct the C# compiler that an integral literal such as 1000 be considered a certain type of number—for example, a long (1000L). We look into how you can add numeric suffixes to numbers.

In your case:

public decimal ConvertedValue 
{
    get
    {
        return BaseValue * (365 / 360M);
    }
}

And also its more clear when you use an Uppercase suffixes:

Lowercase suffixes. You can also specify lowercase suffixes, such as u, l, ul, f, d and m. But these are easier to confuse with numbers. The letter 'l' is sometimes seen as the number 1.


you can just add a m suffix to one of the numbers to make it decimal:

return BaseValue * (365 / 360m);

You can simply use decimal literals, by using the m suffix:

public decimal ConvertedValue 
{
    get
    {
        return BaseValue * (365m/360);
    }
}

The reason why the second cast is redundant, is because C# derives that the first number (365) in your ((double)365 / (double)360) expression is a double. So in order to calculate the division, it will implictly convert the second item to a double as well. So it does not matter whether you write (double) as second element:

csharp> (double) 365/350        
1.04285714285714                
csharp> (double) 365/ (double) 350
1.04285714285714

Nevertheless, it is quite useless to cast to doubles and then back to decimals. By using one decimal literal in your expression, the other number will also be a decimal, and thus we stay in the decimal world.


In your example, you can just leave the brackets away:

return BaseValue*365/360;

You only need one of the double casts. So

return BaseValue * (decimal)(365/(double)360);

will work fine.

Once one is a double, the compiler knows to treat it as non-integer division.

Alternatively

return (BaseValue*365)/360;

will work.

or even

return BaseValue*365/360;

since multiplication is of higher precedence than division.


A double divided by a double is (of course) a double. So casting the result is redundant.

It would be shorter if you simply specify the numbers as decimals:

 return BaseValue * (365m /360);

Either one of the (double) casts are redundant, but not both. If any argument to an operation is double, the other argument is automatically cast to double. Can you write one of the arguments as a real number constant, eg, 365.0 ?


Need Your Help

How to determine previous page URL in Angular?

angular angular2-routing

Suppose I am currently on the page which has the URL /user/:id . Now from this page I navigate to next page :id/posts.

When to use PerThreadLifetimeManager?

dependency-injection unity-container repository-pattern unit-of-work object-lifetime

I am following the example linked to below for setting up unity to work with my service layer. My project is setup very similar to the one in this article and I understand everything except why exa...