19

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...?

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Jakob Busk Sørensen
  • 5,599
  • 7
  • 44
  • 96
  • 2
    Why do you use bracers? Seems like a strong backup strategy if you don't know [precedence rules](https://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx) and [implicit conversion logic](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/implicit-numeric-conversions-table), but it leads to a problem sometimes... – Sinatr Sep 20 '17 at 14:21
  • @Sinatr None of the parentheses in OP's code can be changed without changing the syntax tree of the code. OP's problem isn't that they don't understand precedence: they have correctly identified why the first code snippet does not work. – wchargin Sep 21 '17 at 00:23
  • @Sinatr I know about precedence and "PEMDAS". The parenthesis was partly added to keep the two examples similar, but I also use them to improve readability for other developers. – Jakob Busk Sørensen Sep 21 '17 at 07:54

10 Answers10

26

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

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • 1
    Thanks for the detailed explanation. I ended up using the `m` after the number, which made it work. Does the `m` has any meaning, or is it just an arbitrary symbol, chosen to represent decimals? – Jakob Busk Sørensen Sep 20 '17 at 13:37
  • 1
    @Noceo I guess m stands for money, since this is the adivised type to use when calculating with money values. But rather trust the description of Jon Skeet in [this post](https://stackoverflow.com/questions/977484/what-does-the-m-stand-for-in-c-sharp-decimal-literal-notation) ;) – Mong Zhu Sep 20 '17 at 13:41
  • That could make sense. You never know, if it was simply the work of some dyslectic developer :-) – Jakob Busk Sørensen Sep 20 '17 at 13:49
  • @Noceo :D probably it is really the case. But I think it is more likely that `d` was already given to double, so they chose the next letter that was free ;) – Mong Zhu Sep 20 '17 at 14:14
  • 1
    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. – Banex Sep 20 '17 at 15:45
  • @Banex granted. I will incorporate it into my answer – Mong Zhu Sep 20 '17 at 15:50
8

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;
René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • @Fildor there definitly are precision differences with changing order of calculation, but I guess they also depend on `BaseValue`'s value. – René Vogt Sep 20 '17 at 13:33
4

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

return BaseValue * (365 / 360m);
sofsntp
  • 1,964
  • 23
  • 34
4

use the m suffix:

return 365m/360 * BaseValue;
Zumoka
  • 41
  • 2
4

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.

SᴇM
  • 7,024
  • 3
  • 24
  • 41
2

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.

Yair Halberstadt
  • 5,733
  • 28
  • 60
2

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.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
2

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

return BaseValue*365/360;
Damien Flury
  • 769
  • 10
  • 23
0

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);
0

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 ?

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27