Question

I have two matrices a = [120.23, 255.23669877,...] and b = [125.000083, 800.0101010,...] with double numbers in [0, 999]. I want to use bitxor for a and b. I can not use bitxor with round like this:

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

Because the decimal parts 0.23 and 0.000083 ,... are very important to me. I thought maybe I could do a = a*10^k and b = b*10^k and use bitxor and after that result/10^k (because I want my result's range to also be [0, 999]. But I do not know the maximum length of the number after the decimal point. Does k = 16 support the max range of double numbers in Matlab? Does bitxor support two 19-digit numbers? Is there a better solution?

Was it helpful?

Solution

This is not really an answer, but a very long comment with embedded code. I don't have a current matlab installation, and in any case don't know enough to answer the question in that context. Instead, I've written a Java program that I think may do what you are asking for. It uses two Java classes, BigInteger and BigDecimal. BigInteger is an extended integer format. BigDecimal is the combination of a BigInteger and a decimal scale.

Conversion from double to BigDecimal is exact. Conversion in the opposite direction may require rounding.

The function xor in my program converts each of its operands to BigDecimal. It finds a number of decimal digits to move the decimal point by to make both operands integers. After scaling, it converts to BigInteger, does the actual xor, and converts back to BigDecimal undoing the scaling.

The main point of this is for you to look at the results, and see whether they are what you want, and would be useful to you if you could do the same thing in Matlab. Explaining any ways in which the results are not what you want may help clarify your requirements for the Matlab experts.

Here is some test output. The top and bottom rows of each block are in decimal. The middle row is the scaled integer versions of the inputs, in hex.

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

Here is the Java program:

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

OTHER TIPS

"But I do not know the max length of number after point ..."

In double precision floating-point you have 15–17 significant decimal digits. If you give bitxor double inputs these must be less than intmax('uint64'): 1.844674407370955e+19. The largest double, realmax (= 1.797693134862316e+308), is much bigger than this, so you can't represent everything in the the way you're using. For example, this means that your value of 800.0101010*10^17 won't work.

If your range is [0, 999], one option is to solve for the largest fractional exponent k and use that: log(double(intmax('uint64'))/999)/log(10) (= 16.266354234268810).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top