[英]How can I add an accurate difference column to a DataTable?
I need to compare numeric data from two datatables with the same schema. 我需要比较来自两个数据表的数字数据与相同的模式。 For example two tables with data such as
例如两个包含数据的表
PKColumn |
PKColumn | numCol |
numCol | DecimalCol
DecimalCol
will end up looking like this after the merge 合并后最终会看起来像这样
PKColumn |
PKColumn | numCol 1 |
numCol 1 | numCol 2 |
numCol 2 | numCol Diff |
numCol Diff | DecimalCol 1 |
DecimalCol 1 | DecimalCol 2 |
DecimalCol 2 | DecimalCol Diff
DecimalCol Diff
Initially, I just created the diff column as an expression col1-col2 but I can end up with unusual looking values 最初,我刚刚创建了diff列作为表达式col1-col2,但我最终得到了不寻常的值
col1 col2 diff c1 c2 diff
12.8 14.6 -1.80000019 33.2 29.8 3.40000153
But what I want is: 但我想要的是:
col1 col2 diff c1 c2 diff
12.8 14.6 -1.8 33.2 29.8 3.4
So my current solution is to manually iterate through the rows and set the value using this method: 所以我目前的解决方案是手动迭代行并使用此方法设置值:
private static void SetDifference(DataRow dataRow, DataColumn numericColumn)
{
dynamic value1 = dataRow[numericColumn.Ordinal - 2];
dynamic value2 = dataRow[numericColumn.Ordinal - 1];
if (IsDbNullOrNullOrEmpty(value1) || IsDbNullOrNullOrEmpty(value2)) return;
//now find out the most decimals used and round to this value
string valueAsString = value1.ToString(CultureInfo.InvariantCulture);
int numOfDecimals = valueAsString.SkipWhile(c => c != '.').Skip(1).Count();
valueAsString = value2.ToString(CultureInfo.InvariantCulture);
numOfDecimals = System.Math.Max(numOfDecimals, valueAsString.SkipWhile(c => c != '.').Skip(1).Count());
double result = Convert.ToDouble(value1 - value2);
dataRow[numericColumn] = System.Math.Round(result, numOfDecimals);
}
But it feels clunky and not good for performance. 但它感觉笨重而且不利于表现。 Suggestions for improvements are welcome.
欢迎提出改进建议。
EDIT: changed column names from "int" to "num" to avoid confusion 编辑:将列名从“int”更改为“num”以避免混淆
EDIT: also, I don't always want to round to one decimal spot. 编辑:另外,我并不总是想要舍入到一个小数点。 I may have data like numA: 28 numB: 75.7999954 so I want a diff of: -47.7999954
我可能有数字像numA:28 numB:75.7999954所以我想要一个差异:-47.7999954
If you have columns that store integer numbers then use an integer number type for them! 如果您有存储整数的列,那么为它们使用整数类型! Probably you used a single precision floating point type.
可能你使用的是单精度浮点类型。 The same holds for decimal types.
小数类型也是如此。 Use a decimal column type for them and this rounding problem will vanish!
使用十进制列类型,这个舍入问题将消失!
If you use a true decimal type (not float, single, real or double) you will not encounter rounding problems. 如果使用真十进制类型(不是float,single,real或double),则不会遇到舍入问题。 I do not know which database you are using, but with SQL-Server the correct column type would be
decimal
. 我不知道您使用的是哪个数据库,但使用SQL-Server时,正确的列类型将为
decimal
。
UPDATE UPDATE
Since you cannot change the column type, round it to the requested precision like this 由于您无法更改列类型,因此请将其舍入为所需的精度
result = Math.Round((c1-c2) * 10)/10; // One decimal
result = Math.Round((c1-c2) * 100)/100; // Two decimals
result = Math.Round((c1-c2) * 1000)/1000; // Three decimals
Math.Round(3.141592654 * 10000)/10000 ===> 3.1416
-- -
UPDATE UPDATE
Try this, it should perform well in most cases 试试这个,它在大多数情况下应该表现良好
decimal result = (decimal)col1 - (decimal)col2;
Test 测试
12.8f - 14.6f ===> -1.80000019 (decimal)12.8f - (decimal)14.6f ===> -1.8
Based on Olivier's comments I've updated my code to look like this: 基于Olivier的评论,我已将代码更新为如下所示:
if(numericColumn.DataType == typeof(int))
{
dataRow[numericColumn] = System.Math.Abs(value1 - value2);
}
else
{
dataRow[numericColumn] = Convert.ToDecimal(value1) - Convert.ToDecimal(value2);
}
Seems a lot cleaner and it gets the job done. 看起来更清洁,它完成了工作。 Thanks for the help.
谢谢您的帮助。
你应该在sql查询中使用
ROUND(table1.IntCol 1 - table2.IntCol 2, 1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.