转换为整数时浮点不规则

the*_*yer 0 floating-point ada

我有一个例程,其目的是将浮点数编码为整数(然后将其放入字节流).在此过程中,信息丢失.例程将输出切换为3.33的增量.

因此,0和3.33之间的差距有点奇怪,因为它不是零,而不是3.33.我决定(并非完全任意)任何非零浮动输入应该舍入到3.33(同样,3.34,应该达到6.66等).

这一切都很好.代码如下:

function EncodeFloatingPoint (Value : Long_Float) return Integer is
    Intermediate_Value : Integer;
    Return_Value : Integer := 0;
begin
    -- converts float into 3.33 increments

    -- case 1, positive or zero 
    if (Value >= 0.0) then
        --Ensures rounding away from zero
        Intermediate_Value := Integer((Value * 100.0 + 332.99) / 333.0); 

    -- case 2, negative through -3.33 (up to, but not including zero)
    else

        -- Code omitted, is not problematic
    end if;

    Return_Value := Intermediate_Value;

    return Return_Value;
end
Run Code Online (Sandbox Code Playgroud)

当我0.0在单元测试期间将值传递给我的代码时,会出现问题.单步执行时,转换会产生一个值3.33而不是预期值0.0,并且我的单元测试失败.但是,当我转到GDB控制台并键入时Print Integer((0.0 * 100.0 + 332.99) / 333.0),结果为0(如替换0.0值).我可以确认Value打印到0.0.

会发生什么事?有一种更简单的方法可以确保在将其转换回整数时从零开始舍入吗?

Jef*_*ter 5

你在计算332.99 / 333.0,大概是0.99997.从真实类型到整数类型的转换轮次[ARM 4.6(33)],所以你得到1.我认为你将它解释为3.33.您可能需要特殊情况零:

if Value > Long_Float'Pred (0.0) and Value < Long_Float'Succ (0.0) then
   return 0;
end if;
Run Code Online (Sandbox Code Playgroud)

(注意,在"if"语句的条件下不需要括号.)

您可能还会发现'Remainder属性函数很有用.您应该熟悉ARM A.5.3中的所有浮点属性(实际上是ARM A中的所有标准库).

您似乎正在创建自己的定点类型,其中包含3.33的小定义类型.为什么不让语言为你做这件事?

Result_Delta : constant := 3.33;

type Result_Value is delta Result_Delta
   range Integer'First * Result_Delta .. Integer'Last * Result_Delta
   with Small => Result_Delta;
Run Code Online (Sandbox Code Playgroud)