小数和数学运算

Decimal and mathematical operations

我在 C# 中对 decimal 进行了简单的转换。它看起来像这样:

private decimal BaseValue
{
    get; set;
}

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

但是,这不起作用。我假设是因为 C# 正在将分数中的数字处理为整数。所以我可以这样做(有效):

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

现在这似乎有点矫枉过正,但我​​可以接受。我的主要问题是:

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

你只需要双重演员之一。所以

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

会很好。

一旦 1 是双精度数,编译器就知道将其视为非整数除法。

或者

return (BaseValue*365)/360;

会起作用。

甚至

return BaseValue*365/360;

因为乘法的优先级高于除法。

您可以在其中一个数字后添加一个 m 后缀使其成为十进制:

return BaseValue * (365 / 360m);

解决这个问题的一种方法是指定计算中的数字是 decimal,最后是 m

return BaseValue * (365m / 360m);

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

因为当等式的一侧有 double 时,结果将是双倍的。

(double)365 / (double)360

看看the documentation of the * operator overloads。您会看到操作数始终属于同一类型,例如:

decimal operator *(decimal x, decimal y);


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

同样,因为当等式的一侧有 decimal 时,结果将是小数:

BaseValue * (decimal)(365 / 360)

这里的问题是作用域!您将除法的整个结果投射到 decimal 。其实你可以简单地通过删除括号来解决你的问题:

return BaseValue * 365 / 360;

这样你的等式将是正确的,因为 * 乘法的结果将是 decimal(因为其中一个操作数是 decimal,所以另一个将被隐式转换)并且出于同样的原因,除法的结果也将是小数。

注意: 删除括号通常与保留括号不同。在某些情况下,当此类运算的顺序发生变化时,浮点运算的结果会有所不同,即使这两个表达式在数学上是相同的。 Banex

发表评论

编辑:

m 东西被称为文字。有关所有类型后缀或 文字 的更多信息,请参见 documentation here

双倍除以双倍(当然)是双倍。所以转换结果是多余的。

如果您简单地将数字指定为小数会更短:

 return BaseValue * (365m /360);

您可以简单地使用 十进制文字,通过使用 m 后缀 :

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

第二个转换是多余的,因为 C# 派生出 ((double)365 / (double)360) 表达式中的第一个数字 (365) 是 double。所以为了计算除法,它也会隐式地将第二项转换为 double。所以第二个元素写成(double)没有关系:

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

然而,转换为双精度然后再转换为小数是非常无用的。通过在表达式中使用一个小数文字,另一个数字也将是小数,因此我们留在 decimal 世界中。

decimal 转换是多余的,因为编译器知道你想要 return 一个 decimal.

两个 double 转换中的一个 是多余的,因为当您将 int 之一转换为 double 时,它是明确您使用 double 除法运算符而不是整数除法。

但只使用 decimal 文字后缀 m 就足够了:

return BaseValue * (365m / 360);

同样,一个 m 足以推断出正确的运算符。


但是嘿,BaseValue 已经是 decimal 并且括号没有意义(如果你不想要整数除法)......这也应该有效:

return BaseValue * 365 / 360;

(双重)演员中的任何一个都是多余的,但不是两个都是多余的。 如果操作的任何参数为双精度,则另一个参数会自动转换为双精度。 您能否将其中一个参数写成实数常量,例如 365.0 ?

使用 m 后缀:

return 365m/360 * BaseValue;

某些类型的数字有一些后缀,例如:

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

你的情况:

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

而且当你使用大写后缀时它会更清晰:

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.

在你的例子中,你可以把括号去掉:

return BaseValue*365/360;