How to correctly multiply the decimal type in C#?

Asked

Viewed 521 times

7

I’m multiplying monetary values in C#, and for that I’m using the type decimal to store these values.

I have noticed that in it there is a method called Multiply(), which receives two values and performs multiplication.

But I was in doubt what its usefulness, since for multiplication we just use the operator *

Example:

decimal multiplicacaoComMultiply = decimal.Multiply(50.40M, 3); 
decimal multiplicacaoComOperador = 50.40M * 3;

Console.WriteLine(multiplicacaoComMultiply);
Console.WriteLine(multiplicacaoComOperador);

The result will be:

151,20 // Usando o multiply
151,20 // Usando o operador

Doubts

  • What is the usefulness of this method, since we already have the multiplication operator?
  • Is there any loss of accuracy using the method or the operator?
  • To work with multiplication in which both types are decimal, which is the most recommended use?

According to the documentation of this method, it does not specify the reason or says that it does something more than the operator, such as precision.

1 answer

11


Let’s look at their sources:

public static decimal Multiply(decimal d1, decimal d2) {
    DecCalc.VarDecMul(ref AsMutable(ref d1), ref AsMutable(ref d2));
    return d1;
}

Source.

public static decimal operator *(decimal d1, decimal d2) {
    DecCalc.VarDecMul(ref AsMutable(ref d1), ref AsMutable(ref d2));
    return d1;
}

Source.

They are identical in their conception. I don’t know if purposely or not, but the code is the same (I don’t know if there should be an abstraction there to be more DRY and ensure that you always do the same and have no problem of someone changing one and not the other unintentionally, but it may be that really one day someone may want it to be different, although unlikely). But they’re not identical in all their semantics because of language rules, I’m already saying below

What is the usefulness of this method, since we already have the multiplication operator?

Hard to say. It may be just to give symmetry with other things. But there is a difference that may be a reason to use one or the other:

using static System.Console;

public class Program {
    public static void Main() {
        WriteLine(decimal.Multiply(50.40M, 3));
        WriteLine(50.40M * 3);
//      WriteLine(decimal.Multiply(50.40, 3));
        WriteLine(50.40 * 3);
        WriteLine(decimal.Multiply(50, 3).GetType());
        WriteLine((50 * 3).GetType());
//      decimal x = 1_000_000 * 1_000_000;
        decimal x = decimal.Multiply(1_000_000, 1_000_000);
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

Try taking out the comment. It’s a mistake. You may want to ensure that the type is not automatically promoted, that is, you can only use a value that is genuinely decimal, not just one that can be converted to. With the operator the rule of the language is to allow the promotion occurs, with the method this does not occur, there is no direct promotion established of all numerical types to decimal.

And note the type of each expression. With the method we guarantee that the result will be decimal, with the operator depends, if one of the data is not decimal the result will not be `decimal . The operator overload rule is ambiguous and the preference is to resolve by natural type and not one that can be promoted, nor could it be different.

At last you multiply 2 large numbers and stretch the capacity. Of course if they were literal of type decimal (that end with M) there would be no problem. But even using integers in the method works precisely because of the promotion that int for decimal occurs. In the case of the operator the int that does not support such large numbers and after calculating is that the result would be promoted to decimal, but too late.

All this is a problem of resolution, not that one behaves different from the other in what he proposes to do, but what is called in each situation.

Is there any loss of accuracy using the method or the operator?

No, they’re identical. And since none of this is documented, you can’t change this later.

To work with multiplication in which both types are decimal, which is the most recommended use?

Most readable to the situation, I doubt you have a case other than the operator.

  • In the operator’s documentation * for the structure Decimal states that both the method and the operator are equivalent and that the method is an alternative to languages that do not support customized operators. I just do not know which language . Net that does not give this support.

  • 1

    @Augustovasques this is a good reason for interoperability, I don’t believe they created just for this, but also for this, it doesn’t affect C#, but it can help these other languages. I didn’t mention it because I thought since you have the documentation that the AP saw.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.