22
\$\begingroup\$

Your task is pretty simple. Given two floats, bitwise xor the binary representation of them, and output that as a float.

For example,

Normal: 16.7472 ^ 123.61 = 7.13402e-37
Binary: 01000001100001011111101001000100 ^ 01000010111101110011100001010010 = 00000011011100101100001000010110

Normal: 2.2 ^ 4.4 = 1.17549e-38
Binary: 01000000000011001100110011001101 ^ 01000000100011001100110011001101 = 00000000100000000000000000000000

Normal: 7.898 ^ 3.4444 = 1.47705e-38
Binary: 01000000111111001011110001101010 ^ 01000000010111000110101001111111 = 00000000101000001101011000010101

Restrictions/clarifications:

\$\endgroup\$
20
  • 2
    \$\begingroup\$ Does Boolean list count as a convenient method? \$\endgroup\$
    – Adám
    Commented Sep 15, 2019 at 14:11
  • 28
    \$\begingroup\$ "binary representation" of a float is extremely ambiguous. You'll need to define which representation you're using. There are an infinite number of representations, including the finite number already used by life on this planet, some being more popular than others, such as IEEE 754 \$\endgroup\$ Commented Sep 16, 2019 at 10:07
  • 8
    \$\begingroup\$ This question would be more interesting as "xor the values" rather than "xor the representations". The latter is of course identical to "xor two 32-bit integers" in any language that lacks a type system or admits type punning, and thus is pretty boring... \$\endgroup\$ Commented Sep 16, 2019 at 14:33
  • 5
    \$\begingroup\$ Do we have to handle infinity, subnormals, or negative 0, as either input or output? \$\endgroup\$
    – Grimmy
    Commented Sep 16, 2019 at 16:24
  • 3
    \$\begingroup\$ @Mark: No, as written the question is just about xor'ing their representations, whatever those representations are. The result is dependent on the floating point format but the algorithm is always a single xor instruction on the representation, which is pretty boring. \$\endgroup\$ Commented Sep 17, 2019 at 1:43

22 Answers 22

57
\$\begingroup\$

x86-64 machine code, 4 bytes

0f 57 c1 c3

In assembly:

xorps xmm0, xmm1
ret

This is a callable function that takes two floats or doubles as arguments (in xmm0 and xmm1) and returns a float or double (in xmm0).

That matches the calling conventions of both Windows x64 and the x86-64 SysV ABI, and works for floats as well as doubles. (They're passed / returned in the low 4 or 8 bytes of XMM registers).

\$\endgroup\$
12
\$\begingroup\$

C++ (gcc), 74 32 bytes

#define f(x,y)*(int*)x^=*(int*)y

Try it online!

I haven’t previously golfed in C++ so am grateful to all those who helped halve the size of the code! A macro which takes pointers to two floats as its arguments and modified the first to return the result.

Thanks to @12Me1 for saving 2 bytes and @Arnauld for saving 4! Thanks to @Nishioka for saving another 14, @Neil a further 6 and @AZTECCO and @Nishioka another 11! Thanks to @PeterCordes for saving 5 bytes!

\$\endgroup\$
17
  • 1
    \$\begingroup\$ You can remove the linebreaks to save 2 chars, and this also works in C \$\endgroup\$
    – 12Me21
    Commented Sep 15, 2019 at 16:40
  • 1
    \$\begingroup\$ You can save 4 more bytes with z=*(int*)x^*(int*)y;. \$\endgroup\$
    – Arnauld
    Commented Sep 15, 2019 at 16:46
  • 1
    \$\begingroup\$ With gcc extensions, 54 bytes: #define f(x,y)({int z=*(int*)x^*(int*)y;*(float*)&z;}) \$\endgroup\$
    – Nishioka
    Commented Sep 15, 2019 at 18:34
  • 2
    \$\begingroup\$ Since you're using pointers, is it legal to use one of the inputs as the output? If so, you could write (*(int*)x^=*(int*)y). \$\endgroup\$
    – Neil
    Commented Sep 15, 2019 at 18:47
  • 1
    \$\begingroup\$ Taking into consideration @Neil's suggestion it would get to 48 bytes: #define f(x,y)({*(int*)x^=*(int*)y;*(float*)x;}) \$\endgroup\$
    – Nishioka
    Commented Sep 15, 2019 at 19:00
9
\$\begingroup\$

ARM Thumb Machine Code, 6 4 Bytes

48 40 70 47

In assembly:

EORS R0, R1 ; Exclusive Or of the first two params, store result in the return register
BX LR       ; Branch to the value stored in the Link Register (Return address)

Under the standard Arm calling convention, the first two parameters are passed in the registers R0 and R1, results are returned in R0, and LR holds the return address. Assuming you're using the soft float ABI with 32 bit floats, this will perform the desired operation in 4 bytes.

-2 bytes thanks to Cody Gray

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Would it be possible to use EORS r0, r1 instead, in order to save 2 bytes? That's only a 2-byte instruction (48 40), compared to your 4-byte EOR. You're already targeting Thumb, so this should work fine, as far as I can see. The only difference is it updates status flags, but you don't care about that side effect in this case. \$\endgroup\$
    – Cody Gray
    Commented Sep 17, 2019 at 0:31
  • 2
    \$\begingroup\$ You should specify that this is using the soft-float ABI which passes FP args in integer registers, not VFP / NEON s0 and s1. \$\endgroup\$ Commented Sep 17, 2019 at 7:30
6
\$\begingroup\$

Python 3 + numpy, 75 59 bytes

lambda x,y:(x.view("i")^y.view("i")).view("f")
import numpy

Try it online!

Defines a lambda which takes two numpy float32 arrays as its arguments and returns a numpy float32 array.

Thanks to @ShadowRanger for saving 14 bytes, and Joel a further 2!

If the import can be dropped (since my lambda itself calls methods on numpy objects rather than any base numpy functions), I could save a further 13 bytes. I’m uncertain on this from the code golf standard rules.

\$\endgroup\$
6
  • \$\begingroup\$ It's shorter than Jelly and Ruby answers. Nice! \$\endgroup\$ Commented Sep 17, 2019 at 9:06
  • \$\begingroup\$ You can shave off 27 bytes (dropping it to 48 bytes) by removing the import entirely (just assume the caller passed you numpy.float32s so you can use their methods) and replacing both int32 uses with 'i' and the float32 usage with 'f'; the dtype parameter can be a string which gets converted to the real dtype for you, and conveniently, 'i' and 'f' are legal ways to make those dtypes, which removes the need for the function to import numpy stuff into its namespace at all. Not sure if it's Code Golf legal to remove the import but still assume numpy inputs... \$\endgroup\$ Commented Sep 17, 2019 at 19:41
  • \$\begingroup\$ Example showing it works with the import itself being unavailable to f \$\endgroup\$ Commented Sep 17, 2019 at 19:43
  • \$\begingroup\$ I thought the imports had to be included, but I’m not sure. Thanks for the tip re the dtypes! \$\endgroup\$ Commented Sep 17, 2019 at 19:44
  • \$\begingroup\$ @NickKennedy: Yeah, if the import is required, it only saves 8 bytes (two each from int32 to 'i', four from float32 to 'f'), but that's still something. If the import is strictly required, you could just change it to import numpy to assert the package exists, without using from numpy import* to extract names from it. That would get you another six bytes, down to 61 bytes total. \$\endgroup\$ Commented Sep 17, 2019 at 19:46
6
\$\begingroup\$

Jelly + numpy, 89 77 bytes

“(F(“I^F(“IvF).item()”;"F“¢lẒṾ:/²)Ɓɱ¡vẠ⁷5Rʠ¡7ɼṆṪ{ė4¶Gẉn`¡Ð}ṫȥṄo{b»Ḳ¤¹ṣḢ}jʋƒŒV

Try it online!

Has the dubious honour of being longer than the Python 3 code it reproduces, largely because of the need to convert to/from numpy objecte and the fact that numpy isn’t loaded by Jelly so the __import__() built-in has to be used.

A monadic link taking the two floats as a list as its argument and returning a float.

Evaluates the following Python 3 code:

(__import__('numpy').float32(x).view("i")^__import__('numpy').float32(y).view("i")).view(__import__('numpy').float32).item()

where x and y are substituted with the input.

\$\endgroup\$
5
\$\begingroup\$

APL (Dyalog Unicode), 14 bytesSBCS

Full program. Prompts for 1-column matrix of two IEEE 754 64-bit floating-point numbers (binary64) from stdin. Prints one such number to stdout.

645⎕DR≠⌿11⎕DR⎕

Try it online!

 prompt (numbers that collapse to non-floats can be forced into floats with the function ⊃⊢⎕DR⍨645,⍨⎕DR)

11⎕DR convert to 1-bit Binary (1) Data Representation (2-row, 64-column matrix)

≠⌿ vertical XOR reduction

645⎕DR convert to 64-bit float (5) Data Representation (single number)

\$\endgroup\$
0
5
\$\begingroup\$

VAX BASIC (later VMS BASIC, then Compaq Basic), 11 bytes

H = F XOR G

Seems a bit silly to me, obviously, older languages will do better because they didn't worry abut strong-typing issues as much.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to the site and nice first answer! I've edited out what appears to be an extraneous header, but if not feel free to edit it back in, along with any accompanying information \$\endgroup\$ Commented Sep 16, 2019 at 14:20
3
\$\begingroup\$

Octave, 59 bytes

@(a,b)(t=@typecast)(bitxor(t(a,u='int32'),t(b,u)),'single')

Try it online!

Typecast is the MATLAB/Octave way of casting without changing the underlying bits. This is required because bitxor only works on integers. No idea why they never implemented floating point numbers, even though you can explicitly specify the AssumedType as a third argument to bitxor. I guess the only use is recreational programming.

\$\endgroup\$
1
  • \$\begingroup\$ Bitwise stuff on FP bit patterns is useful in assembly language to do things with the sign bit, or rarely to stuff an integer into the exponent field as part of an exp() implementation. But I assume Octave already has functions/operators for copysign and negation. And they don't care about micro-optimizations like using AND (with a constant mask) then XOR to conditionally flip the sign of one value based on the sign of another. In a real optimization project in asm (actually C with AVX intrinsics) I have used XOR of floats then looking at the sign bit to avoid cmp against zero. \$\endgroup\$ Commented Sep 17, 2019 at 7:36
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 92 bytes

x=>BitConverter.Int32BitsToSingle(x.Aggregate(0,(a,b)=>a^BitConverter.SingleToInt32Bits(b)))

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could use unsafe code for this, though I'm not sure if the "unsafe" keyword should affect the bytecount or not. \$\endgroup\$ Commented Sep 15, 2019 at 18:41
2
\$\begingroup\$

Perl 5 -p, 31 27 bytes

-4 bytes thanks to Grimy

$\=unpack f,$a^=pack f,$_}{

Try it online!

\$\endgroup\$
0
2
\$\begingroup\$

MATL, 10 bytes

4Z%Z}Z~9Z%

Try it online!

Splitting with Z} was shorter than taking two inputs ,4Z%]

\$\endgroup\$
2
\$\begingroup\$

C, 23 bytes

f(int*x,int*y){*x^=*y;}

Try it online!

This might be a bit shifty; it takes the pointers to floats as pointers to ints.

However, it does work (this is C after all).

This takes advantage of acceptable input by taking a pointer to the variable and modifying it in-place. No (usable) value is returned.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js),  105  101 bytes

Shorter Node version suggested by @Neil
Saved 4 more bytes thanks to @ShieruAsakoto

Takes input as (x)(y).

x=>y=>(v=Buffer(4),v.writeInt32LE((g=n=>v.writeFloatLE(n)&&v.readInt32LE())(x)^g(y)),v.readFloatLE())

Try it online!


JavaScript (ES6), 115 bytes

Takes input as an array of 2 floats.

a=>(v=new DataView(new ArrayBuffer(4))).getFloat32(v.setUint32([x,y]=a.map(n=>v.getUint32(v.setFloat32(0,n))),x^y))

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ FYI Node's Buffer saves a few bytes: a=>(v=new Buffer(4),[x,y]=a.map(n=>v.writeFloatLE(n)&&v.readInt32LE()),v.writeInt32LE(x^y),v.readFloatLE()). \$\endgroup\$
    – Neil
    Commented Sep 15, 2019 at 18:57
  • \$\begingroup\$ @Neil Thanks! (saved 2 more bytes by using a function instead of map) \$\endgroup\$
    – Arnauld
    Commented Sep 15, 2019 at 21:50
  • 1
    \$\begingroup\$ Dropping the new in new Buffer(4) should also work iirc \$\endgroup\$ Commented Sep 19, 2019 at 14:36
2
\$\begingroup\$

Java (JDK), 109 76 63 bytes

a->b->a.intBitsToFloat(a.floatToIntBits(a)^a.floatToIntBits(b))

Try it online!

Been a while since I golfed in Java and I'm not certain if I need the declaration on the LHS as part of the byte count? If it used DoubleBinaryOperator the LHS would be shorter, but the RHS would have to use Double.doubleToLongBits and Double.longBitsToDouble, so that's actually longer.

Thanks to Neil for a substantial savings on the byte count!

Thanks to Unmitigated for currying the way to another improvement!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ IIRC you don't even need the assignment as part of the byte count, only as part of any test suite you might include in your Try it online! header. \$\endgroup\$
    – Neil
    Commented Sep 18, 2019 at 12:37
  • \$\begingroup\$ @Neil Thank you! That makes a big difference! \$\endgroup\$ Commented Sep 18, 2019 at 18:01
  • \$\begingroup\$ 63 bytes: a->b->a.intBitsToFloat(a.floatToIntBits(a)^a.floatToIntBits(b)). Try it online! \$\endgroup\$ Commented Nov 23, 2021 at 3:25
  • 1
    \$\begingroup\$ @Unmitigated Thank you! Excellent currying! \$\endgroup\$ Commented Nov 26, 2021 at 3:49
1
\$\begingroup\$

Wolfram Mathematica, 50 bytes

BitXor@@(FromDigits[RealDigits[#,2,32,0][[1]],2]&)

Although I strongly suspect that this could be more golfed, the two extra arguments in RealDigits function seem to be necessary for getting a correct result.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Lua, 73 bytes

a,b=('II'):unpack(('ff'):pack(...))print((('f'):unpack(('I'):pack(a~b))))

Try it online!

This code assumes 4-bytes unsigned integers and floats which is configuration on tio.run. Run as full program with input as arguments.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 78 67 bytes

-11 bytes thanks to @grawity.

->x{[x.pack("gg").unpack("NN").inject(&:^)].pack(?N).unpack(?g)[0]}

Try it online!

Input is an array of two floats.

\$\endgroup\$
2
  • \$\begingroup\$ x.map{|v|[v].pack(?g).unpack(?N)[0]}x.pack("gg").unpack("NN") \$\endgroup\$
    – user1686
    Commented Sep 18, 2019 at 12:32
  • \$\begingroup\$ @grawity: Awesome, thank you very much! The code is still longer than in Python, though. :-/ \$\endgroup\$ Commented Sep 18, 2019 at 13:35
1
\$\begingroup\$

MMIX, 8 bytes (2 instrs)

Really, just put in an xor command.

00000000: c600 0001 f801 0000                      İ¡¡¢ẏ¢¡¡
xorflt  XOR $0,$0,$1
        POP 1,0

Simples.

\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 40 bytes

~=reinterpret
!x=Float64~⊻((Int~x)...)

Try it online!

expects Float64s on a 64 bit platform. On a 32 bit platform, use Float32

\$\endgroup\$
0
\$\begingroup\$

Clean, 36 bytes

f::!Real!Real->Real
f _ _=code{xor%}

Try it online!

Thankfully the Real and Int types are the same sizes on 64-bit platforms...
Unfortunately requires a complete signature otherwise the graph turns into a pretzel and everything segfaults.

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 87 bytes

x=>(v=Buffer(8),x.map((c,i)=>v.writeFloatLE(c,h=4*i)),v.map(e=>e^v[h++]).readFloatLE())

Try it online!

silly

\$\endgroup\$
0
\$\begingroup\$

Factor, 40 bytes

[ [ float>bits ] bi@ bitxor bits>float ]

Try it online!

                     ! 2.2 4.4
[ float>bits ] bi@   ! 1074580685 1082969293
bitxor               ! 8388608
bits>float           ! 1.175494350822288e-38
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.