实数中的杂散小数值

问题描述 投票:0回答:1

我有一个实数

delay
,我想将其转换为 10 的第一个倍数。例如,如果延迟 = 0.0024,我希望输出为 240。

在以下代码片段中,

delay
= 1.52e-6。在
while
循环执行之后,我预计
delay
为 1520。但是,在
delay
循环之后,我看到
while
= 1.52e17。我检查了波形,看起来
delay
的值是1.5200000000000001e-6。为什么会这样呢?我是不是做错了什么?

这是代码:

  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
verilog system-verilog
1个回答
0
投票

为什么会这样?

如果您在运行模拟时使用中间值,您就会明白为什么会发生这种情况。这比查看波形更明显,波形只会显示

$display
循环完成后的最终值。这是一个可运行的代码示例:
while

输出:

module tb; real delay = 1.52e-6; function real mod (real a, real b); mod = a - b*$floor(a/b); $display("a=%g, floor=%g, mod=%g", a, $floor(a/b), mod); endfunction initial begin $display(delay); while (mod(delay, 10) != 0) delay = delay*10; $display(delay); end endmodule

我做错了什么吗?

是的。问题是您在
1.52e-06 a=1.52e-06, floor=0, mod=1.52e-06 a=1.52e-05, floor=0, mod=1.52e-05 a=0.000152, floor=0, mod=0.000152 a=0.00152, floor=0, mod=0.00152 a=0.0152, floor=0, mod=0.0152 a=0.152, floor=0, mod=0.152 a=1.52, floor=0, mod=1.52 a=15.2, floor=1, mod=5.2 a=152, floor=15, mod=2 a=1520, floor=152, mod=2.27374e-13 a=15200, floor=1520, mod=1.81899e-12 a=152000, floor=15200, mod=2.91038e-11 a=1.52e+06, floor=152000, mod=2.32831e-10 a=1.52e+07, floor=1.52e+06, mod=1.86265e-09 a=1.52e+08, floor=1.52e+07, mod=2.98023e-08 a=1.52e+09, floor=1.52e+08, mod=2.38419e-07 a=1.52e+10, floor=1.52e+09, mod=1.90735e-06 a=1.52e+11, floor=1.52e+10, mod=3.05176e-05 a=1.52e+12, floor=1.52e+11, mod=0.000244141 a=1.52e+13, floor=1.52e+12, mod=0.00195312 a=1.52e+14, floor=1.52e+13, mod=0.03125 a=1.52e+15, floor=1.52e+14, mod=0.25 a=1.52e+16, floor=1.52e+15, mod=2 a=1.52e+17, floor=1.52e+16, mod=0 1.52e+17

循环中的比较检查没有按照您期望的方式工作。您不应该像这样将

while
值与 0 进行比较。相反,您需要将其与某个相当小的值进行比较。例如:
real

这将为您提供所需的输出:
while (mod(delay, 10) > 1e-12) delay = delay*10;

这是完整的输出:

1520

这是
浮点比较

的普遍问题。

© www.soinside.com 2019 - 2024. All rights reserved.