转换浮点"> ="到">"和"< ="到"<"

时间:2015-03-13 18:12:37

标签: delphi simd delphi-xe4

我正在寻找一种方法在Delphi中获取最小的单浮点值和双浮点值,我可以添加或减去或添加到我的数字,以使浮点数比较的数字不同。或者,如果我可以获得比我的数字更小和更大的下一个浮点数。从浮点的角度来看,我想转换一下:

if (A >= B) or (C <= D) then

if (A > newnumber1) or (C < newnumber2) then

它们在浮点数上产生相同的结果。对于单身和双打,newnumber1newnumber2显然会有所不同。我需要一些值,我可以减去我的A并添加到我的C值以获得newnumber1和newnumber2,或者我需要一种从B和D获取这些数字的方法。

在C ++ 11中,有一个方法std::nextafter在这个问题中引用,看起来就足够了。

Finding the closest floating point value less than a specific integer value in C++?

上下文

我正在做矢量操作,我需要做相当于大于或等于的操作。实现此目的的最简单方法是采用稍微小一些的数字,并使用大于操作的数字。如果可能的话,我宁愿不要嘲笑似乎有效的价值。

我使用的矢量操作是ippsThreshold_LTValGTVal_32s来自:

https://software.intel.com/en-us/node/502143

图书馆显然不支持&gt; =操作。这在浮点意义上是不实际的。要创建一个等效函数,我需要增加和减少我的比较值来计算它,然后使用大于操作和小于操作。

例如

如果我有5个值的数组[99.4,20,19.9,99,80],ippsThreshold_LTValGTVal_32s向量操作将允许我用我自己的替换值替换向量中的特定值。在这个例子中,我想用0替换所有值&gt; = 99和&lt; = 20.要做到这一点,我想传递这样的东西。因此,我必须用略小的东西替换99,而用稍微大一点的东西取代20。

函数签名如下所示:

ippsThreshold_LTValGTVal_32s(..., ..., ..., levelLT, valueLT, levelGT, valueGT);

我的电话会是这样的:

ippsThreshold_LTValGTVal_32s(..., ..., ..., 20.00000001, 0, 98.99999, 0);

然后,这将包括用于小于操作的20和用于大于操作的99,并且给我一个看起来像[0,0,0,0,80]的向量。

我需要找出20.0000001和98.999999的用途。我希望这些值和原始值之间的差异尽可能小,同时仍然足够重要,以包括&gt;中的值。和&lt;操作

1 个答案:

答案 0 :(得分:6)

按照设计,对于IEEE754数据类型,您可以简单地将值视为整数并增加该值。如果值为负,则递减它。

function NextDoubleGreater(const D: Double): Double;
var
  SpecialType: TFloatSpecial;
  I: Int64;
begin
  SpecialType := D.SpecialType;
  case SpecialType of
  fsZero,fsNZero:
    // special handling needed around 0 and -0
    I := 1;
  fsInf, fsNInf, fsNaN:
    I := PInt64(@D)^; // return the original value
  fsDenormal, fsNDenormal, fsPositive, fsNegative:
    begin
      I := PInt64(@D)^;
      if I >= 0 then begin
        inc(I);
      end else begin
        dec(I);
      end;
    end;
  end;
  Result := PDouble(@I)^;
end;

同样在相反的方向:

function NextDoubleLess(const D: Double): Double;
var
  SpecialType: TFloatSpecial;
  I: Int64;
begin
  SpecialType := D.SpecialType;
  case SpecialType of
  fsZero,fsNZero:
    // special handling needed around 0 and -0
    I := $8000000000000001;
  fsInf, fsNInf, fsNaN:
    I := PInt64(@D)^; // return the original value
  fsDenormal, fsNDenormal, fsPositive, fsNegative:
    begin
      I := PInt64(@D)^;
      if I >= 0 then begin
        dec(I);
      end else begin
        inc(I);
      end;
    end;
  end;
  Result := PDouble(@I)^;
end;

格式是这样的,这并非巧合。由于这种设计,浮点比较运算符的实现是微不足道的。

参考:How to alter a float by its smallest increment (or close to it)?