# linq到SQL Math.ROUND问题[英] LINQ to SQL Math.Round Problem ### 问题描述

```Sales =
... // Joins here
orderby cust.State ascending
select new Sale
{
InvoiceLine = inv.InvoiceLine,
InvoiceNum = inv.InvoiceNum,
...
NetPrice = Math.Round((inv.ExtPrice - inv.Discount) * (Decimal) (qsales.RepSplit / 100.0), 2, MidpointRounding.ToEven),
}).ToList<Sale>();
```

NetPrice成员具有300.000000、5000.500000、3245.250000等值之类的值

# 编辑:

DECIMAL.ROUND做到了​​这一技巧(我忘了提到NetPrice成员是十进制类型).请参阅下面的答案.

## 其他推荐答案

``` var s = dec.ToString("#.00");
```

.

```var x = new decimal(1.01) - (decimal)0.01;
var y = new decimal(2.02) - (decimal)0.02;
Console.WriteLine(x * y * x * x);
```

## 其他推荐答案

System.Decimal按设计保留尾随的零.换句话说，1m和1.00m是两个不同的decimal s(尽管它们将以相等的比较)，并且可以解释为被舍入到不同数量的小数位 - 例如Math.Round(1.001m)将给出1m，Math.Round(1.001m, 2)将给出1.00m.算术运算符对其进行不同的处理 - +和-将产生与具有大多数的操作数相同的位置(SO *)，并且*和/将具有相同的位置数量其操作数的位置数量(So 1.00m * 1.000m == 1.00000m).

### 问题描述

I'm having an issue with a query I wrote where for some reason the variable that I'm using to store a decimal value in returns 6 values after the decimal place (they're mostly 0).

I have tried the following (and different combinations using Math.Round) with no luck.

```Sales =
... // Joins here
orderby cust.State ascending
select new Sale
{
InvoiceLine = inv.InvoiceLine,
InvoiceNum = inv.InvoiceNum,
...
NetPrice = Math.Round((inv.ExtPrice - inv.Discount) * (Decimal) (qsales.RepSplit / 100.0), 2, MidpointRounding.ToEven),
}).ToList<Sale>();
```

The NetPrice member has values like 300.000000, 5000.500000, 3245.250000, etc.

Any clues? I can't seem to find anything on this issue online.

## EDIT:

Decimal.Round did the trick (I forgot to mention that the NetPrice member was a Decimal type). See my answer below.

## 推荐答案

I got it to work using Decimal.Round() with the same arguments as before. :)

Looks like the issue is somewhat on the trail of what Pavel was saying, where Decimal types behave differently and it would seem Math.Round doesn't quite work with them as one would expect it to...

Thanks for all the input.

## 其他推荐答案

Trailing zeros can appear in the output of .ToString on the decimal type. You need to specify the number of digits after the decimal point you want display using the correct format string. For example:-

``` var s = dec.ToString("#.00");
```

display 2 decimal places.

Internally the decimal type uses an integer and a decimal scaling factor. Its the scaling factor which gives rise to the trailing 0. If you start off with a decimal type with a scaling factor of 2, you will get 2 digits after the decimal point even if they are 0.

Adding and substracting decimals will result in a decimal which has a scaling factor of the is the maximum of the decimals involved. Hence subtracting one decimal with a scaling factor of 2 from another with the same the resulting decimal also has a factor of 2.

Multiplication and division of decimals will result in a decimal that has a scaling factor that is the sum of the scaling factors of the two decimal operands. Multiplying decimals with a scaling factor of 2 results in a new decimal that has a scaling factor of 4.

Try this:-

```var x = new decimal(1.01) - (decimal)0.01;
var y = new decimal(2.02) - (decimal)0.02;
Console.WriteLine(x * y * x * x);
```

You get 2.00000000.

## 其他推荐答案

System.Decimal preserves trailing zeroes by design. In other words, 1m and 1.00m are two different decimals (though they will compare as equal), and can be interpreted as being rounded to different number of decimal places - e.g. Math.Round(1.001m) will give 1m, and Math.Round(1.001m, 2) will give 1.00m. Arithmetic operators treat them differently - + and - will produce a result that has the the same number of places as the operand which has most of them (so 1.50m + 0.5m == 1.10m), and * and / will have the sum of number of places for their operands (so 1.00m * 1.000m == 1.00000m).