Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#小数类型舍入不当_C#_Sql Server_Floating Point_Rounding Error - Fatal编程技术网

C#小数类型舍入不当

C#小数类型舍入不当,c#,sql-server,floating-point,rounding-error,C#,Sql Server,Floating Point,Rounding Error,我有一个夏令营的内部银行解决方案,我是夏令营的一部分。接下来的问题是,一些账户在本赛季结束时正好被减了一分钱 我使用的是SQL Server Express,有两个表。一个包含所有账户的表,其中保存了账户的当前余额。另一个表是正在运行的事务日志。这个想法是,如果我要对日志中的所有事务进行汇总,它应该等于任何给定帐户的当前帐户余额 但事实并非如此。例如,我对数据库求和,发现给定的帐户应该有$15.10,但帐户表显示它们的余额为$15.09 以下是相关代码: //Amount is negative

我有一个夏令营的内部银行解决方案,我是夏令营的一部分。接下来的问题是,一些账户在本赛季结束时正好被减了一分钱

我使用的是SQL Server Express,有两个表。一个包含所有账户的表,其中保存了账户的当前余额。另一个表是正在运行的事务日志。这个想法是,如果我要对日志中的所有事务进行汇总,它应该等于任何给定帐户的当前帐户余额

但事实并非如此。例如,我对数据库求和,发现给定的帐户应该有
$15.10
,但帐户表显示它们的余额为
$15.09

以下是相关代码:

//Amount is negative, they bought something
if (amount <= 0)
{
    //Check if they have enough money to buy, or they are a paid account type (faculty, staff)

    if (account.Balance >= Math.Abs(amount) || account.AccountType > AccountType.Camper)
        account.Balance -= Math.Abs(amount);
    else
        return Error.LowBalance;
}
else
{
    account.Balance += Math.Abs(amount);
}

var t = new Transaction
{
    AccountId = account.Id,
    Amount = amount,
    SubmittedBy = username,
    TransactionRefId = refId,
    ComputerHostname = hostname,
    Location = location,
    Notes = notes
};

_db.Transactions.Add(t);
_db.SaveChanges();
//金额为负数,他们买了东西
if(amount=Math.Abs(amount)| | account.AccountType>AccountType.Camper)
账户余额-=数学资产负债表(金额);
其他的
返回错误。低平衡;
}
其他的
{
账户余额+=数学资产负债表(金额);
}
var t=新交易
{
AccountId=account.Id,
金额=金额,
SubmittedBy=用户名,
TransactionRefId=refId,
计算机主机名=主机名,
位置=位置,
注释=注释
};
_db.Transactions.Add(t);
_db.SaveChanges();
我使用的是实体框架,首先是代码。
账户.余额
金额
交易.金额
的数据类型均为
系统十进制

我不明白为什么会有舍入错误,我正在使用所有适合这种情况的数据类型。我看到这一点的通常方式是,当他们有两个不同的交易,
$0.75
。出于某种原因,代码显示
0.05+0.05=0.09

在我的数据库中,
Accounts.Balance
列的数据类型是
decimal(18,2)


我知道浮点数有时可以做到这一点,但我正在寻找解决办法。我以为我已经使用了
系统.Decimal
数据类型了。

您只存储了2个十进制数字,然后丢弃了后面的所有内容,在这个过程中失去了精度。存储更多的十进制数字


另一个丢失精度的例子:

您只存储了2个十进制数字,并将其后面的所有内容都丢弃,从而在存储过程中丢失了精度。存储更多的十进制数字


另一个丢失精度的例子:

你所说的“代码表示0.05+0.05=0.09”是什么意思?不清楚您在哪里看到了什么。您是否可以使用调试器找到导致舍入错误的确切代码行?您是否尝试过将类型更改为Money@这似乎就是正在发生的事情。如果我申请一笔0.75美元的交易,然后再申请一笔0.75美元的交易,系统显示余额等于1美元。49@AdamSchiavone如果这是正确的(老实说,我怀疑不是),那么你应该能够很容易地找到一个最小的复制机。编写一个程序,将属性设置为
1.50m
,并将其保存到数据库中。如果它存储的不是
1.50
,则编辑您的问题以显示具有该行为的程序。如果它存储了
1.50
,那么问题不在于你说的是什么。你所说的“代码是说0.05+0.05=0.09”是什么意思?不清楚您在哪里看到了什么。您是否可以使用调试器找到导致舍入错误的确切代码行?您是否尝试过将类型更改为Money@这似乎就是正在发生的事情。如果我申请一笔0.75美元的交易,然后再申请一笔0.75美元的交易,系统显示余额等于1美元。49@AdamSchiavone如果这是正确的(老实说,我怀疑不是),那么你应该能够很容易地找到一个最小的复制机。编写一个程序,将属性设置为
1.50m
,并将其保存到数据库中。如果它存储的不是
1.50
,则编辑您的问题以显示具有该行为的程序。如果它存储
1.50
,那么问题不在于你说的是什么。所以我需要将
decimal(18,2)
更改为类似
decimal(18,4)
?或者更多,取决于你想要的可靠性,C中的decimal只是一个“多位的双精度”,但也不能被信任。我不相信这个答案适用。这篇文章是关于当你将一个10位小数的数字保存到一个只有2位小数的db字段中时的截断。它是截断的,不是圆形的。在他的情况下,数据库有足够的空间来正确存储值。@AlexandreBorela
decimal
不仅仅是更高的精度
double
decimal
类型将值表示为整数乘以10的幂(从技术上讲,始终是10的负幂),而不是2的幂。这意味着
decimal
可以精确地表示1/5(2*10^-1),而
double
不能。这与建议的解决方案直接相关。因此,我需要将
十进制(18,2)
更改为类似
十进制(18,4)
?或更多,取决于您想要的可靠性,C#中的十进制只是一个“具有更多位的双精度”,但也不能被信任。我不相信这个答案适用。这篇文章是关于当你将一个10位小数的数字保存到一个只有2位小数的db字段中时的截断。它是截断的,不是圆形的。在他的情况下,数据库有足够的空间来正确存储值。@AlexandreBorela
decimal
不仅仅是更高的精度
double
decimal
类型将值表示为整数乘以10的幂(从技术上讲,始终是10的负幂),而不是2的幂。这意味着
decimal
可以精确地表示1/5(2*10^-1),而
double
不能。这与提议的解决方案直接相关。