前言
我正在研究一个系统,该系统旨在供不理解浮点算术的人使用。因此,浮点数比较的实现不会暴露给使用该系统的人。目前,浮点数的比较是这样进行的(由于历史原因,不能更改):
// If either number is not finite, do default comparison
if (!IsFinite(num1) || !IsFinite(num2)) {
output = (num1 == num2);
} else {
// Get exponents of both numbers to determine epsilon for comparison
tmp = (OSINT32*)&num1+1;
exp1 = (((*tmp)>>20)& 0x07ff) - 1023;
tmp = (OSINT32*)&num2+1;
exp2 = (((*tmp)>>20)& 0x07ff) - 1023;
// Check if exponent is the same
if (exp1 != exp2) {
output = false;
} else {
// Calculate epsilon based on the magic number 47 (presumably calculated experimentally)?
epsilon = pow(2.0,exp1-47);
output = (fabs(num2-num1) <= eps);
}
}
问题的关键是,我们根据数字的指数计算epsilon,以防止用户在接口中进行浮点比较时犯错误。 一个重要提示:这是针对非软件程序员的人,因此当他们执行pow(sqrt(2), 2) == 2
时,他们不会感到惊讶。也许这不是最好的想法,但正如我所说,它不能改变。
问题
我们遇到了如何向用户显示数字的问题。过去,他们只是将数字显示为15个有效数字。但这会导致以下类型的问题:
>> SHOW 4.1 MOD 1
>> 0.099999999999999996
>> SHOW (4.1 MOD 1) == 0.1
>> TRUE
比较结果称其正确是由于epsilon的生成。但是数字的打印会令人困惑,为什么0.099999999999999996等于0.1?我们需要一种方法来显示数字,使它代表与之比较为TRUE所需的最短有效位数。因此,对于0.099999999999999996,这将是0.1,对于0.569999999992724327,这将是0.569999999992725。
这是否可能?