Floating point 转换为整数时的浮点不规则性

Floating point 转换为整数时的浮点不规则性,floating-point,ada,Floating Point,Ada,我有一个例程,其目的是将浮点数编码为整数(然后将其放入字节流)。在这个过程中,信息丢失了。例行程序将输出分成3.33的增量 所以,0和3.33之间的差距有点奇怪,因为它不是零,也不是3.33。我决定(并非完全武断地)任何非零浮点输入都应该四舍五入到3.33(同样,3.34应该四舍五入到6.66,以此类推) 这一切都很好。代码如下: function EncodeFloatingPoint (Value : Long_Float) return Integer is Intermediat

我有一个例程,其目的是将浮点数编码为整数(然后将其放入字节流)。在这个过程中,信息丢失了。例行程序将输出分成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
当我在单元测试期间将值
0.0
传递到我的代码中时,就会出现此问题。逐步执行时,转换结果为
3.33
,而不是预期的
0.0
,并且我的单元测试失败。但是,当我转到GDB控制台并键入
Print Integer((0.0*100.0+332.99)/333.0)
时,结果是预期的0(用
0.0
替换值)。我可以确认该值打印为0.0

会发生什么事?在将其转换回整数时,是否有更简单的方法确保从零取整?

如果查看,您将看到浮点类型有一个属性函数
“天花板”
,它生成“大于或等于X的最小(最负)整数值”(传递的参数)


因此,请尝试:
四舍五入:=浮点型上限(未四舍五入)

您正在计算的
332.99/333.0
,约为0.99997。从实数类型到整数类型的转换将[ARM 4.6(33)],因此得到1。我猜你把它解释为3.33。您可能需要使用特殊情况0:

if Value > Long_Float'Pred (0.0) and Value < Long_Float'Succ (0.0) then
   return 0;
end if;

与float进行的equals比较不会像与定点进行比较那样有效。如果不是负数,您可以尝试,但是对于一种/某些浮点格式,负零是可能的。这不是一个等于的问题-经过转换的值是3.33,它以这种方式打印出来。我只是不明白为什么。你的价值很可能不是零,加上一个值=零的案例,与其他案例分开,看看你是否真的陷入其中。这有很多层,编译器使用库,gdb使用库和代码。IEEE-754有多种舍入模式可用,上下舍入,向零舍入,等等。但是每种语言都支持这些吗?如果是这样,如何指定这些舍入模式?这是一个单元测试,该值被专门初始化为
0.0
->编译器需要
.0
。我们使用的是gcc。这就完成了任务,尽管我仍然很好奇为什么在调试控制台中传入
0.0
会产生预期的输出,而当从编译代码传入常量
0.0
时,它不会产生预期的输出……我无法回答这个问题。但是我不认为编译器需要使用与源文本中列出的
0.0
Ada.text\u IO.Float\u IO
解析的
0.0
完全相同的版本。
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;