我有一个实数delay
,我想将其转换为 10 的第一个倍数。例如,如果延迟 = 0.0024,我希望输出为 240。
在以下代码片段中,delay
= 1.52e-6。循环执行后while
,我预计为 1520。但是,循环后delay
我看到= 1.52e17 。我检查了波形,看起来 的值最初是 1.5200000000000001e-6。为什么会这样呢?难道我做错了什么?delay
while
delay
这是代码:
real delay = 1.52e-6;
function real mod (real a, real b);
mod = a - b*$floor(a/b);
endfunction
initial begin
while (mod(delay, 10) != 0) delay = delay*10;
end
注意相当。
浮点类型通常使用binary64等进行编码。这种 64 位编码可以精确地编码大约 2 64个不同的值。1.52e-6 不是其中之一,因为它不是二进有理数(某个整数乘以 2 的幂)。相反,代码开始使用附近的值 1.5200000000000000582720720634921640623815619619563e-06 或 0x198059AC99A685 * 2 -72。
由于许多会
delay = delay*10
产生舍入误差,因此会出现进一步的复杂情况。修改目标或使用不同的方法。
“转换为 10 的第一个倍数”听起来像是次要目标。更高层次的目标是什么?
注意:所有有限浮点值都是精确的。我们对它们进行操作的方式常常导致结果与我们在学校学到的确切数学结果不同。
如果您
$display
在运行模拟时使用中间值,您就会明白为什么会发生这种情况。这比查看波形更明显,波形只会显示while
循环完成后的最终值。这是一个可运行的代码示例:输出:
是的。问题是
while
循环中的比较检查没有按照您期望的方式工作。你不应该real
像这样将值与 0 进行比较。相反,您需要将其与某个相当小的容差值进行比较。例如:这将为您提供所需的输出:
1520
这是完整的输出:
所有浮点变量类型都存在不确定性。有时,像这样的直接比较
!=
会起作用,而有时则不起作用。它不能保证有效,这就是为什么容差值会有所帮助。这是浮点比较的常见问题。