如果 A<B == true 如果 A 和 B 是 Doubles。我将位复制到两个 uint64_t 将 A<B 仍然为真

Posted

技术标签:

【中文标题】如果 A<B == true 如果 A 和 B 是 Doubles。我将位复制到两个 uint64_t 将 A<B 仍然为真【英文标题】:If A<B == true if A and B are Doubles. It I copy to the Bits to two uint64_t will A<B still be true 【发布时间】:2021-03-14 02:50:08 【问题描述】:

我正在使用一些加密库和零知识证明做一些事情,而我使用的库仅支持整数。

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

A_Double>B_Double==A_UINT>B_UINT

适用于所有值。

我的猜测是它可能适用于所有正值,但不适用于负值。

虽然如果我翻转第一位可能会起作用。

【问题讨论】:

这能回答你的问题吗? Comparing floats in their bit representations 如果忽略 NaN 值,如果设置了符号位,则需要翻转除符号位之外的所有值。然后你可以做有符号整数比较。 你没有说明使用的是什么浮点格式。 【参考方案1】:

接近尾声

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

a &lt; 0 的整数版本翻转时,折叠到0footnote,所以+0.0 和-0.0 比较相等。 FP 值通常被编码为 sign-magnitude

同时寻找 Nan 编码。


A 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);

测试

#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");


footnote 通过折叠负数使 0000_0000_0000_0000 和 8000_0000_0000_0000 都是“零”,最负的“作为整数的双精度”值将比最负的可编码整数多 1,从而防止 UB 在llabs() 计算。

【讨论】:

感谢这是最有用的,尽管我使用的是不同的语言,但它很容易遵循和实施。特别是因为我能够实现一个只使用正数的更简单的实现。【参考方案2】:

您没有说明使用的浮点格式。 IEEE 754 和大多数浮点系统使用有效的符号和数量格式。最高有效位的位是符号位。取反值是通过翻转符号位来完成的。相反,对二进制补码格式的值取反是通过翻转所有位并加一来完成的。

浮点格式通常在符号位之后是表示值的下一个最高有效位、指数位,然后是有效位。这样做的结果是对于两个正浮点数 xyx > y 是等价的到 x > y,其中 x 和 y 是将 xy 的位重新解释为无符号整数或二进制补码整数。然而,对于两个负浮点数,x > y 等价于 x

此外,浮点格式通常具有非数字值,称为 NaN。使用这些值,整数比较会失败,因为浮点比较被定义为对于所有比较都是错误的 - NaN 不小于、等于或大于数字或 NaN。

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

【讨论】:

以上是关于如果 A<B == true 如果 A 和 B 是 Doubles。我将位复制到两个 uint64_t 将 A<B 仍然为真的主要内容,如果未能解决你的问题,请参考以下文章

php 使用操作符

php 等于不等于 一个感叹号两个等于号

python 比较运算符和逻辑运算符

给定 2 个 int 值,如果一个是负数,另一个是正数,则返回 True

[转] Hive函数大全

比较(即关系)运算符