Ada定点乘法舍入

Ada fixed-point rounding of multiplication

以下代码打印 TRUE,这意味着 0.0191*0.0191 正在评估 0.0003,而 0.0192*0.0192 正在评估 0.0004。然而:

0.0191*0.0191 = 0.00036481
0.0192*0.0192 = 0.00036864

如果四舍五入发生在 0.00035 的阈值处,则相应的平方根阈值应该是 0.0187

如果我把delta改成10.0**(-5),就不是这样了。

所以我的问题是 "How rounding of fixed-point calculation works in this situation?"

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   type T is delta 10.0**(-4) range 0.0 .. 10.0;

   X1 : T := 0.0191;
   X2 : T := 0.0192;
   Y : T := 0.0004;
   B : Boolean;
begin
   B := (X1 * X1 = Y - T'Delta) and (X2 * X2 =Y);
   Put_Line(B'Image);
end Main;

我不认为 'rounding' 是这里的问题。

你说

type T is delta 10.0**(-4) range 0.0 .. 10.0;

这意味着 (Put_Line (T'Small'Image);) T 的最低有效位是 6.103515625E-05.

这是2的第一个二进制次幂小于delta; ARM 3.5.9(8) 仅要求它小于或等于增量。

因此,0.0191 在二进制中表示为 312,乘以 'Small 得到 1.904296875E-02,其平方为 3.62634658813477E-04,除以 'Small 得到二进制表示是 5.94140625E+00。 GNAT 使用 ARM 4.5.5(21) ("for ordinary fixed point types, if the mathematical result is between two multiples of the small, it is unspecified which of the two is the result") 中的权限将其转换为 5,对应于 3.0517578125E-04,打印时四舍五入为您的 0.0003 结果。

0.0192二进制表示为314,结果为6.017822265625E+00,转为6,对应3.662109375E-04,打印四舍五入为0.0004。

你会发现我乱用了你的代码来获取这些数字!

您可能要考虑

Delta_T : constant := 10.0 ** (-4);
type T is delta Delta_T range 0.0 .. 10.0 with Small => Delta_T;