c# - 匹配优于 C# 应用程序中的舍入
问题描述
我目前正在将用于计算科学值的相当高的 Excel 工作表转换为 C# 应用程序。但是,我在四舍五入方面遇到了一些问题。
我所有的值都存储为双精度值,当您对它们执行少量操作时,它们在可接受的精度(5 或 6 个小数位)内匹配 excel 表。当他们通过除法,乘法,平方根进行相当大的运算时。他们开始以相当大的幅度漂移。我在另一个点将整个代码库切换为小数,以测试它是否解决了这个问题,它缩小了差距,但问题仍然存在。
我知道这是由于软件开发中十进制数的性质,但我必须尽可能匹配 excel 的舍入。对这个主题的研究将我指向 excel 用于舍入的标准,而且 C# 默认情况下使用的标准似乎略有不同。尽管了解了这一点,但我仍然不确定如何继续复制 excels 舍入。我想知道是否有人对此主题有任何建议或以前的经验?
任何帮助将不胜感激。
编辑:我只想澄清一下,我并没有四舍五入我的数字。工作表和我的代码上的舍入都被隐式应用。我在一个完全不同的软件包(一个名为 K2 的表单生成器)中测试了相同的公式。结果数字与我的 c# 应用程序匹配,因此它似乎擅长隐式舍入在某些方面有所不同。
有问题的公式之一:
(8.04 * Math.Pow(10, -5)) *
(Math.Pow(preTestTestingDetails.PitotCp, 2)) * (DeltaH) *
(tempDGMAverage + 273.0) /
(StackTemp + 273) *
((preTestTestingDetails.BarometricPressure / 0.133322 +
((preTestTestingDetails.StackStaticPressure / 9.80665) / 13.6)) /
(preTestTestingDetails.BarometricPressure / 0.133322)) *
(preTestTestingDetails.EstimatedMolWeight /
((preTestTestingDetails.EstimatedMolWeight * (1 - (EstimatedMoisture / 100))) +
(18 * (EstimatedMoisture / 100)))) *
Math.Pow((1 - (EstimatedMoisture / 100)), 2) *
(Math.Pow(preTestTestingDetails.NozzleMean, 4));
解决方案
在 C# 中的结果
int x = 5;
var result = x / 2; // result is 2 and of type int
...因为执行整数除法。因此,如果涉及整数(不是double
没有小数的 a,而是int
or类型的值long
),请确保double
在除法之前转换为。
int x = 5;
double result = x / 2; // result is 2.0 because conversion to double is made after division
这有效:
int x = 5;
var result = (double)x / 2; // result is 2.5 and of type double
int x = 5;
var result = x / 2.0; // result is 2.5 and of type double
int x = 5;
var result = 0.5 * x; // result is 2.5 and of type double
公式中唯一可能发生这种情况的地方是EstimatedMoisture / 100
,如果EstimatedMoisture
是类型int
。如果是这种情况,请使用 修复它EstimatedMoisture / 100.0
。
代替8.04 * Math.Pow(10, -5)
,你可以写8.04e-5
。这避免了Math.Pow
!的舍入效应
我不知道如何Math.Pow(a, b)
工作,但一般公式是a^b=exp(b*ln(a))
. 所以与其写Math.Pow(something, 2)
,不如写something * something
。这既更快又更准确。
对幻数使用常量可以增加清晰度。对常见的子表达式使用 temps 可使公式更具可读性。
const double mmHg_to_kPa = 0.133322;
const double g0 = 9.80665;
var p = preTestTestingDetails;
double moisture = EstimatedMoisture / 100.0;
double dryness = 1.0 - moisture;
double pressure_mmHg = p.BarometricPressure / mmHg_to_kPa;
double nozzleMean2 = p.NozzleMean * p.NozzleMean;
double nozzleMean4 = nozzleMean2 * nozzleMean2;
double result = 8.04E-05 *
p.PitotCp * p.PitotCp * DeltaH * (tempDGMAverage + 273.0) / (StackTemp + 273.0) *
((pressure_mmHg + p.StackStaticPressure / g0 / 13.6) / pressure_mmHg) *
(p.EstimatedMolWeight / (p.EstimatedMolWeight * dryness + 18.0 * moisture)) *
dryness * dryness * nozzleMean4;
如果需要考虑精度,为什么不使用 273.15 而不是 273.0?
推荐阅读
- react-native - 如何有条件地禁用带有自定义图标的 react-native HeaderBackButton?
- javascript - 获取已定义坐标的图层和要素
- regex - 如何将正则表达式应用于列并将正则表达式匹配组保存到多个列中?
- android - 绘图的自定义视图未显示
- python-3.x - Python,从函数返回变量
- c# - 我可以将 .Contains 用于整数列表吗?
- java - 如何在构造函数中使用 LocalDate 字段将 JSON 反序列化为 Kotlin 类
- unit-testing - RxJS 单元测试:传递给 TestScheduler 的回调的功能是什么
- primefaces - 为 JSF 页面加载图标或消息
- python - 查找元组对列表中的第一个元素