将浮点数“>=”转换为“>”,“<=”转换为“<”

Converting floating point ">=" to ">" and "<=" to "<"

我正在 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

该库显然不支持 >= 操作。这在浮点意义上是不实用的。要创建一个等效函数,我需要增加和减少我的比较值来解决这个问题,然后使用大于运算和小于运算。

例如

如果我有一个包含 5 个值 [99.4, 20, 19.9, 99, 80] 的数组,ippsThreshold_LTValGTVal_32s 向量运算将让我用自己的替换值替换向量中的特定值。在此示例中,我想用 0 替换所有 >= 99 和 <= 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 的用途。我希望这些值与原始值之间的差异尽可能小,同时仍然足够重要以将值包含在 > 和 < 操作中。

根据设计,对于 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 := 00000000000001;
  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)?