我正在创建一个简单的数学函数来使用 .Net Framework 4.7.2 比较两个数字
原来的函数是这个
public static bool AreNumbersEquals(float number, float originalNumber, float threshold) =>
(number >= originalNumber - threshold) && (number <= originalNumber + threshold);
Run Code Online (Sandbox Code Playgroud)
但令我惊讶的是,当我使用这个语句测试它时
var result = AreNumbersEquals(4.14f, 4.15f, 0.01f);
Run Code Online (Sandbox Code Playgroud)
返回值是false
所以我使用这段代码分割函数
namespace ConsoleApp1_netFramework
{
internal class Program
{
static void Main(string[] args)
{
var qq = AreNumbersEquals(4.14f, 4.15f, 0.01f);
}
public static bool AreNumbersEquals(float number, float originalNumber, float threshold)
{
var min = originalNumber - threshold;
var max = originalNumber + threshold;
var minComparison = number >= min;
var maxComparison = number <= max;
// result1 is true (as expected)
var result1 = minComparison && maxComparison;
// result2 is false (why?)
var result2 = number >= originalNumber - threshold && number <= originalNumber + threshold;
return result2;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在result1如预期为true ,但result2为false
谁能解释一下吗?
更新 1:我了解浮点数和算术在 CPU 级别的工作方式。我对这种特殊情况感兴趣,因为在高层次上,计算是相同的,所以我期望两种编写比较的方式得到相同的结果。
我当前正在从事的项目是一个游戏,因此由于算术计算中涉及的性能损失,因此尽可能避免双精度和小数。
更新 2:当为 64 位架构编译时,条件返回 true,但当为 32 位架构编译时,条件返回 false。
谁能解释一下吗?
是的。对于result1,您将中间结果分配给一个float变量,这会强制它返回 32 位 - 可能会截断结果。(由于这些是局部变量,因此结果可能不会被截断。这部分的规范很棘手。)
对于result2,您正在执行“内联”比较,这允许以更高的精度完成所有算术和比较,这可能会改变结果。
从根本上说,4.14f、4.15f 和 0.01f并不完全是 4.14、4.15 和 0.01……所以任何假设它们是的东西都可能存在一些微妙的问题。这些浮点文字的精确值是:
正如您所看到的,如果您使用这些值手动进行算术,您确实会发现该数字超出了阈值。中间值精度的损失导致了第一次测试的差异。
| 归档时间: |
|
| 查看次数: |
182 次 |
| 最近记录: |