【问题标题】:Double numbers and bitxor [duplicate]双数和位异或[重复]
【发布时间】:2013-08-11 13:47:32
【问题描述】:

我有两个矩阵 a = [120.23, 255.23669877,...]b = [125.000083, 800.0101010,...],在 [0, 999] 中有两个数字。我想将bitxor 用于ab。我不能像这样使用bitxorround

result = bitxor(round(a(1,j),round(b(1,j))

因为小数部分 0.23 和 0.000083 ,... 对我来说非常重要。我想也许我可以做 a = a*10^kb = b*10^k 并使用 bitxor 之后使用 result/10^k (因为我希望我的结果范围也是 [0, 999]。但我不知道小数点后的数字。k = 16在Matlab中是否支持双数的最大范围?bitxor是否支持两个19位数字?有更好的解决方案吗?

【问题讨论】:

  • 您希望xor(120.23, 125.000083) 的结果是什么?
  • XOR 通常只为位数组定义。它仅针对整数定义,因为整数是管理位的便捷方式。通常,两个整数的 XOR 在数学上并不有趣。感兴趣的是底层位。因此,将 XOR 扩展到带有小数部分的数字是不正常的,并且没有被普遍定义。如果您需要这方面的帮助,您必须准确地指定您想要什么结果,包括在我们有两个仅近似十进制数字的浮点数的情况下您想要什么结果。首先,回答哈罗德的问题。
  • @PaulR:我不确定这是不是重复的。根据 OP 的最新评论,看起来他们要么想要对浮点数的底层编码进行异或,要么对整个值(包括小数位)进行异或,就好像它们是二进制数字一样。像在建议的副本中那样转换为整数将不会完成其中任何一个。
  • @saZas:您必须回答以下问题:当 120.325 与 120.75 异或时,结果是什么?当最接近 120.23 的双精度(包含一些舍入误差)与最接近 120.000083 的双精度异或时,结果是什么?
  • 请注意,如果您有两个 doublexy 并且您尝试对它们的二进制数字进行异或(例如,11.001 与 3.125),那么通常无法使用结果与xy 之一恢复另一个。这是因为 xy 的有效位通常不会在值上完全重合(一个的最高有效位比另一个更高,最低有效位更高),所以结果XOR 将包含比double 有效位更多的有效位,并且结果必须四舍五入,这会丢失一些位。

标签: matlab floating-point bit-manipulation xor bitwise-xor


【解决方案1】:

这并不是真正的答案,而是带有嵌入式代码的很长的注释。我没有当前的 matlab 安装,并且在任何情况下都没有足够的知识来回答这种情况下的问题。相反,我编写了一个 Java 程序,我认为它可以满足您的要求。它使用两个 Java 类,BigInteger 和 BigDecimal。 BigInteger 是一种扩展的整数格式。 BigDecimal 是 BigInteger 和小数位数的组合。

从 double 到 BigDecimal 的转换是精确的。反方向的转换可能需要四舍五入。

我的程序中的函数xor 将其每个操作数转换为BigDecimal。它找到一些十进制数字来移动小数点以使两个操作数都成为整数。缩放后,它转换为 BigInteger,执行实际的异或,然后转换回 BigDecimal 以撤消缩放。

这样做的主要目的是让您查看结果,看看它们是否是您想要的,如果您可以在 Matlab 中做同样的事情,这对您很有用。解释结果不是您想要的任何方式可能有助于阐明您对 Matlab 专家的要求。

这是一些测试输出。每个块的顶行和底行都是十进制的。中间一行是输入的缩放整数版本,以十六进制表示。

Testing operands 1.100000000000000088817841970012523233890533447265625, 2
2f0a689f1b94a78f11d31b7ab806d40b1014d3f6d59 xor 558749db77f70029c77506823d22bd0000000000000 = 7a8d21446c63a7a6d6a61df88524690b1014d3f6d59
1.1 xor 2.0 = 2.8657425494106605

Testing operands 100, 200.0004999999999881765688769519329071044921875
2cd76fe086b93ce2f768a00b22a00000000000 xor 59aeee72a26b59f6380fcf078b92c4478e8a13 = 7579819224d26514cf676f0ca932c4478e8a13
100.0 xor 200.0005 = 261.9771865509636

Testing operands 120.3250000000000028421709430404007434844970703125, 120.75
d2c39898113a28d484dd867220659fbb45005915 xor d3822c338b76bab08df9fee485d1b00000000000 = 141b4ab9a4c926409247896a5b42fbb45005915
120.325 xor 120.75 = 0.7174277813579485

Testing operands 120.2300000000000039790393202565610408782958984375, 120.0000830000000036079654819332063198089599609375
d298ff20fbed5fd091d87e56002df79fc7007cb7 xor d231e5f39e1db18654cb8c43d579692616a16a1f = a91ad365f0ee56c513f215d5549eb9d1a116a8
120.23 xor 120.000083 = 0.37711627930683345

这是Java程序:

import java.math.BigDecimal;
import java.math.BigInteger;

public class Test {
  public static double xor(double a, double b) {
    BigDecimal ad = new BigDecimal(a);
    BigDecimal bd = new BigDecimal(b);
    /*
     * Shifting the decimal point right by scale will make both operands
     * integers.
     */
    int scale = Math.max(ad.scale(), bd.scale());
    /*
     * Scale both operands by, in effect, multiplying by the same power of 10.
     */
    BigDecimal aScaled = ad.movePointRight(scale);
    BigDecimal bScaled = bd.movePointRight(scale);
    /*
     * Convert the operands to integers, treating any rounding as an error.
     */
    BigInteger aInt = aScaled.toBigIntegerExact();
    BigInteger bInt = bScaled.toBigIntegerExact();
    BigInteger resultInt = aInt.xor(bInt);
    System.out.println(aInt.toString(16) + " xor " + bInt.toString(16) + " = "
        + resultInt.toString(16));
    /*
     * Undo the decimal point shift, in effect dividing by the same power of 10
     * as was used to scale to integers.
     */
    BigDecimal result = new BigDecimal(resultInt, scale);
    return result.doubleValue();
  }

  public static void test(double a, double b) {
    System.out.println("Testing operands " + new BigDecimal(a) + ", " + new BigDecimal(b));
    double result = xor(a, b);
    System.out.println(a + " xor " + b + " = " + result);
    System.out.println();
  }

  public static void main(String arg[])
  {
    test(1.1, 2.0);
    test(100, 200.0005);
    test(120.325, 120.75);
    test(120.23, 120.000083);
  }
}

【讨论】:

    【解决方案2】:

    “但我不知道点后数字的最大长度......”

    double precision floating-point 中,您有 15–17 个有效十进制数字。如果你给bitxor 双输入,这些必须小于intmax('uint64'): 1.844674407370955e+19。最大的双精度数 realmax (= 1.797693134862316e+308) 比这大得多,因此您无法以您使用的方式表示所有内容。例如,这意味着您的值 800.0101010*10^17 将不起作用。

    如果您的范围是 [0, 999],一种选择是求解最大小数指数 k 并使用它:log(double(intmax('uint64'))/999)/log(10) (= 16.266354234268810)。

    【讨论】:

    • 但是使用 typecast 的结果不在 [0,999] 和我想要的 Return Process 之间,使用 bitxor(result(1,j), b(1,j)) = a 的结果跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多