Floating point 如果A<;如果A和B是双精度的,则B==真。如果我将其复制到两个uint64的位,则A<;B仍然是真的

Floating point 如果A<;如果A和B是双精度的,则B==真。如果我将其复制到两个uint64的位,则A<;B仍然是真的,floating-point,binary,integer,64-bit,bit,Floating Point,Binary,Integer,64 Bit,Bit,我正在做一些关于加密库和零知识证明的工作,我使用的库只支持整数 如果有两个数字存储为双精度浮点,我将每个数字的位复制成一个整数,然后比较整数 A_Double>B_Double==A_UINT>B_UINT 对于所有值 我的猜测是,对于所有的正值,它都可能起作用,但对于负值则不起作用 虽然如果我翻转第一位,它可能会工作。您没有说明使用的浮点格式。IEEE 754和大多数浮点系统使用的格式有效地表示符号和大小。最高有效位置的位是符号位。通过翻转符号位来对值求反。相反,在2的补码格式中

我正在做一些关于加密库和零知识证明的工作,我使用的库只支持整数

如果有两个数字存储为双精度浮点,我将每个数字的位复制成一个整数,然后比较整数

A_Double>B_Double==A_UINT>B_UINT
对于所有值

我的猜测是,对于所有的正值,它都可能起作用,但对于负值则不起作用


虽然如果我翻转第一位,它可能会工作。

您没有说明使用的浮点格式。IEEE 754和大多数浮点系统使用的格式有效地表示符号和大小。最高有效位置的位是符号位。通过翻转符号位来对值求反。相反,在2的补码格式中求反是通过翻转all位并添加1来完成的

浮点格式通常在符号位之后是表示值的次重要位、指数位,然后是有效位位。这样做的结果是,对于两个正浮点数x和y,x>y相当于x>y,其中x和y是x和y的位作为无符号整数或2的补码整数的重新解释。但是,对于两个负浮点数,x>y等于x 此外,浮点格式通常具有非数值,称为NaN。对于这些值,整数比较将失败,因为所有比较的浮点比较都定义为false—NaN不小于、等于或大于数字或NaN

总之,您通常不希望使用浮点值位的整数解释来比较浮点值。

非常接近

关于浮点编码有很多假设:

a<0
的整数版本翻转该值时,在0脚注处折叠,因此+0.0和-0.0比较相等。FP值通常编码为符号大小

还可以查找Nan编码


C解

#include <stdint.h>
#include <stdlib.h>

_Static_assert(sizeof(int64) == sizeof(double), "Unexpected sizes");

#define INT_NAN_TEST(a) (llabs(a) > 0x7FF0000000000000u)

/*
 * Compare 2 integers as is they overlay a same size, same endian 64-bit `double`.
 * Return -1,0,1 when they compare a > b, a===b, a< b
 * or `'?` for un-comparable as at least one of `a,b` is NaN
 *
 * This code assumes a lot about the representation of a `double`.
 * Same size
 * Same endian
 * FP with leading sign bit, then a biased exponent, then significand
 */
int cmp_double(int64_t a, int64_t b) {
  if (a < 0) {
    a = 0x8000000000000000 - a;
  }
  if (b < 0) {
    b = 0x8000000000000000 - b;
  }
  if (INT_NAN_TEST(a) || INT_NAN_TEST(b))
    return '?';
  return (a > b) - (a < b);
}
#包括
#包括
_静态断言(sizeof(int64)=sizeof(double),“意外大小”);
#定义内部测试(a)(LLAB(a)>0x7FF0000000000000u)
/*
*比较两个整数,因为它们覆盖了相同的大小、相同的尾数64位'double'。
*当他们比较a>b,a==b,ab)-(a
试验

#包括
#包括
#包括
#包括
#包括
#包括
int main(){
常数双d[]={0.0,DBL_真_最小,DBL_最小,1,DBL_最大,无穷大,-0.0,
-DBL_真_最小,-DBL_最小,-1,-DBL_最大,-无穷大,NAN};
尺寸n=sizeof d/sizeof*d;
对于(大小i=0;ib)-(a


脚注:通过折叠负数,使0000_0000_0000_0000_0000和8000_0000_0000_0000_0000均为“零”,最负的“双精度整数”值将比最负的可编码整数多1,从而防止UB在
llabs()
计算中出现。

这是否回答了您的问题?如果忽略NaN值,则如果设置了符号位,则需要翻转除符号位以外的所有值。然后您可以进行有符号整数比较。您没有说明使用的是什么浮点格式。感谢这是最有用的,尽管我使用的是另一种语言,但它很容易理解和实现。特别是因为我能够实现一个只使用正数的简单得多的实现。
#include <stdlib.h>
#include <stdio.h>
#include <float.h>
#include <limits.h>
#include <string.h>
#include <math.h>

int main() {
  const double d[] = {0.0, DBL_TRUE_MIN, DBL_MIN, 1, DBL_MAX, INFINITY, -0.0,
      -DBL_TRUE_MIN, -DBL_MIN, -1, -DBL_MAX, -INFINITY, NAN};
  size_t n = sizeof d / sizeof *d;
  for (size_t i = 0; i < n; i++) {
    double a = d[i];
    int64_t ai;
    memcpy(&ai, &a, sizeof ai);
    for (size_t bb = 0; bb < n; bb++) {
      double b = d[bb];
      int64_t bi;
      memcpy(&bi, &b, sizeof bi);
      int cmp_d = (isnan(a) || isnan(b)) ? '?' : (a > b) - (a < b);
      int cmp_i = cmp_double(ai, bi);
      if (cmp_d != cmp_i) {
        printf("% 20g %16llX % 20g %16llX: %2d %2d\n", a, 1llu * ai, b,
            1llu * bi, cmp_d, cmp_i);
      }
    }
  }
  puts("Done");
}