Floating Point XOR

15

Votre tâche est assez simple. Étant donné deux flottants, x ou leur représentation binaire au niveau du bit, et affichez-les comme un flottant.

Par exemple,

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:

  • L'entrée / sortie peut être donnée par n'importe quelle méthode pratique .
  • Le programme peut être un programme complet ou simplement une fonction; n'importe quel.
  • Le type flottant peut être de n'importe quelle taille, mais la taille minimale est de 2 octets.
  • Les failles standard sont interdites.
  • Le code le plus court gagne.
virchau13
la source
2
La liste booléenne est-elle considérée comme une méthode pratique?
Adám
23
La "représentation binaire" d'un flotteur est extrêmement ambiguë. Vous devrez définir la représentation que vous utilisez. Il existe un nombre infini de représentations, y compris le nombre fini déjà utilisé par la vie sur cette planète, certaines étant plus populaires que d'autres, comme IEEE 754
Reversed Engineer
7
Cette question serait plus intéressante comme "xou les valeurs " plutôt que "xou les représentations". Ce dernier est bien sûr identique à "xor two 32-bit integers" dans n'importe quelle langue qui n'a pas de système de type ou qui admet le punning de type, et est donc assez ennuyeux ...
R .. GitHub STOP HELPING ICE
5
Faut-il gérer l'infini, les sous-normales ou le 0 négatif, en entrée ou en sortie?
Grimmy
3
@Mark: Non, tel qu'écrit, la question concerne uniquement la représentation de leurs représentations, quelles que soient ces représentations. Le résultat dépend du format à virgule flottante mais l'algorithme est toujours une instruction xor unique sur la représentation, ce qui est assez ennuyeux.
R .. GitHub STOP HELPING ICE

Réponses:

53

code machine x86-64, 4 octets

0f 57 c1 c3

En montage:

xorps xmm0, xmm1
ret

Il s'agit d'une fonction appelable qui prend deux flottants ou doubles comme arguments (dans xmm0et xmm1) et renvoie un flottant ou double (dans xmm0).

Cela correspond aux conventions d'appel de Windows x64 et de l'Axe SysV x86-64, et fonctionne pour les flottants ainsi que pour les doubles. (Ils sont passés / retournés dans les 4 ou 8 octets les plus bas des registres XMM).

Harold
la source
12

C ++ (gcc) , 74 32 octets

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

Essayez-le en ligne!

Je n'ai jamais joué au golf en C ++ donc je suis reconnaissant à tous ceux qui ont aidé à réduire de moitié la taille du code! Une macro qui prend des pointeurs sur deux flottants comme arguments et modifie le premier pour renvoyer le résultat.

Merci à @ 12Me1 pour avoir sauvé 2 octets et @Arnauld pour en avoir sauvé 4! Merci à @Nishioka pour avoir sauvé 14 autres, @Neil 6 autres et @AZTECCO et @Nishioka 11 autres! Merci à @PeterCordes pour avoir économisé 5 octets!

Nick Kennedy
la source
1
Vous pouvez supprimer les sauts de ligne pour enregistrer 2 caractères, et cela fonctionne également dans C
12Me21
1
Vous pouvez enregistrer 4 octets supplémentaires avec z=*(int*)x^*(int*)y;.
Arnauld
1
Avec extensions gcc, 54 octets:#define f(x,y)({int z=*(int*)x^*(int*)y;*(float*)&z;})
Nishioka
2
Puisque vous utilisez des pointeurs, est-il légal d'utiliser l'une des entrées comme sortie? Si oui, vous pourriez écrire (*(int*)x^=*(int*)y).
Neil
1
En tenant compte de la suggestion de @ Neil, il arriverait à 48 octets:#define f(x,y)({*(int*)x^=*(int*)y;*(float*)x;})
Nishioka
9

Code ARM Thumb Machine, 6 4 octets

48 40 70 47

En montage:

EORS R0, R1; Exclusif Ou des deux premiers paramètres, stocker le résultat dans le registre de retour
BX LR; Branche à la valeur stockée dans le registre des liens (adresse de retour)

Selon la convention d'appel standard Arm, les deux premiers paramètres sont passés dans les registres R0 et R1, les résultats sont retournés dans R0 et LR contient l'adresse de retour. En supposant que vous utilisez le soft float ABI avec des flottants 32 bits, cela effectuera l'opération souhaitée en 4 octets.

-2 octets grâce à Cody Gray

Sir_Lagsalot
la source
2
Serait-il possible d'utiliser à la EORS r0, r1place, afin d'économiser 2 octets? Ce n'est qu'une instruction de 2 octets (48 40 ), par rapport à votre 4 octets EOR. Vous ciblez déjà Thumb, donc cela devrait fonctionner correctement, autant que je sache. La seule différence est qu'il met à jour les indicateurs de statut, mais vous ne vous souciez pas de cet effet secondaire dans ce cas.
Cody Gray
2
Vous devez spécifier qu'il utilise l'ABI à flotteur doux qui transmet les arguments FP dans les registres entiers, et non VFP / NEON s0et s1.
Peter Cordes
6

Python 3 + numpy, 75 59 octets

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

Essayez-le en ligne!

Définit un lambda qui prend deux tableaux numpy float32 comme arguments et renvoie un tableau numpy float32.

Merci à @ShadowRanger pour avoir sauvé 14 octets, et à Joel 2 autres!

Si l'importation peut être abandonnée (puisque mon lambda lui-même appelle des méthodes sur des objets numpy plutôt que sur des fonctions numpy de base), je pourrais économiser 13 octets supplémentaires. Je ne suis pas sûr à ce sujet des règles standard du code de golf.

Nick Kennedy
la source
C'est plus court que les réponses Jelly et Ruby. Agréable!
Eric Duminil
Vous pouvez raser 27 octets (en le réduisant à 48 octets) en supprimant entièrement l'importation (supposez simplement que l'appelant vous a transmis numpy.float32afin que vous puissiez utiliser leurs méthodes) et en remplaçant les deux int32utilisations par 'i'et l' float32utilisation avec 'f'; le dtypeparamètre peut être une chaîne qui est convertie en réel dtypepour vous, et de manière pratique, 'i'et 'f'sont des moyens légaux de créer ces dtypes, ce qui supprime la nécessité pour la fonction d'importer des numpyéléments dans son espace de noms. Je ne sais pas si le code Golf est légal pour supprimer l'importation, mais suppose toujours des numpyentrées ...
ShadowRanger
Je pensais que les importations devaient être incluses, mais je n'en suis pas sûr. Merci pour le conseil concernant les dtypes!
Nick Kennedy
@NickKennedy: Oui, si l'importation est requise, elle n'économise que 8 octets (deux chacun de int32à 'i', quatre de float32à 'f'), mais c'est toujours quelque chose. Si l'importation est strictement requise, vous pouvez simplement la modifier import numpypour affirmer que le package existe, sans utiliser from numpy import*pour en extraire des noms. Cela vous donnerait encore six octets, jusqu'à 61 octets au total.
ShadowRanger
6

Gelée + numpy, 89 77 octets

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

Essayez-le en ligne!

A l'honneur douteux d'être plus long que le code Python 3 qu'il reproduit, en grande partie à cause de la nécessité de convertir vers / à partir de numpy objecte et du fait que numpy n'est pas chargé par Jelly donc le __import__() intégré doit être utilisé.

Un lien monadique prenant les deux flottants comme liste comme argument et renvoyant un flottant.

Évalue le code Python 3 suivant:

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

xet ysont remplacés par l'entrée.

Nick Kennedy
la source
5

APL (Dyalog Unicode) , 14 octets SBCS

Programme complet. Demande une matrice à 1 colonne de deux nombres à virgule flottante 64 bits IEEE 754 (binaire64) de stdin. Imprime un de ces nombres sur la sortie standard.

645DR≠⌿11DR

Essayez-le en ligne!

 invite (les nombres qui se réduisent à des non-flottants peuvent être forcés en flottants avec la fonction ⊃⊢⎕DR⍨645,⍨⎕DR)

11⎕DR convertir en binaire 1 bit (1) Représentation D ata R (matrice à 2 lignes et 64 colonnes)

≠⌿ réduction XOR verticale

645⎕DR convertir en float 64 bits (5) Représentation D ata R (nombre unique)

Adam
la source
4

VAX BASIC (plus tard VMS BASIC, puis Compaq Basic) , 11 octets

H = F XOR G

Cela me semble un peu idiot, évidemment, les anciennes langues feront mieux parce qu'elles ne se préoccupaient pas autant des problèmes de frappe forte.

RBarryYoung
la source
1
Bienvenue sur le site et belle première réponse! J'ai édité ce qui semble être un en-tête superflu, mais si ce n'est pas le cas, n'hésitez pas à le rééditer, ainsi que toutes les informations qui l'accompagnent
caird coinheringaahing
3

Octave , 59 octets

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

Essayez-le en ligne!

Typecast est la manière MATLAB / Octave de caster sans changer les bits sous-jacents. Ceci est nécessaire car bitxorne fonctionne que sur des entiers. Aucune idée pourquoi ils n'ont jamais implémenté de nombres à virgule flottante, même si vous pouvez explicitement spécifier le AssumedTypecomme troisième argument de bitxor. Je suppose que la seule utilisation est la programmation récréative.

Sanchises
la source
Les trucs au niveau du bit sur les modèles de bits FP sont utiles en langage assembleur pour faire des choses avec le bit de signe, ou rarement pour bourrer un entier dans le champ exposant dans le cadre d'une exp()implémentation. Mais je suppose qu'Octave a déjà des fonctions / opérateurs pour la copie et la négation. Et ils ne se soucient pas des micro-optimisations comme l'utilisation de AND (avec un masque constant) puis de XOR pour inverser conditionnellement le signe d'une valeur en fonction du signe d'une autre. Dans un vrai projet d'optimisation en asm (en fait C avec intrinsèques AVX), j'ai utilisé XOR de flottants puis en regardant le bit de signe pour éviter cmp contre zéro.
Peter Cordes
2

C, 23 octets

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

Essayez-le en ligne!

Cela pourrait être un peu sournois; il prend les pointeurs vers floats comme pointeurs versint s.

Cependant, cela fonctionne (c'est C après tout).

Cela profite d'une entrée acceptable en prenant un pointeur sur la variable et en la modifiant en place. Aucune valeur (utilisable) n'est retournée.

SS Anne
la source
2

JavaScript (Node.js) ,  105  101 octets

Version plus courte du nœud proposée par @Neil
Économise 4 octets supplémentaires grâce à @ShieruAsakoto

Prend l'entrée comme (x)(y).

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

Essayez-le en ligne!


JavaScript (ES6), 115 octets

Prend l'entrée comme un tableau de 2 flottants.

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

Essayez-le en ligne!

Arnauld
la source
Pour votre information , nœud de Bufferenregistre quelques octets: a=>(v=new Buffer(4),[x,y]=a.map(n=>v.writeFloatLE(n)&&v.readInt32LE()),v.writeInt32LE(x^y),v.readFloatLE()).
Neil
@Neil Merci! (enregistré 2 octets de plus en utilisant une fonction au lieu de map)
Arnauld
1
Laissant tomber le newdans new Buffer(4)doit aussi travailler IIRC
Shieru Asakoto
1

Wolfram Mathematica , 50 octets

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

Bien que je soupçonne fortement que cela pourrait être plus joué, les deux arguments supplémentaires en RealDigitsfonction semblent être nécessaires pour obtenir un résultat correct.

Essayez-le en ligne!

polfosol ఠ_ఠ
la source
1

Lua , 73 octets

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

Essayez-le en ligne!

Ce code suppose des entiers non signés de 4 octets et des flottants sur lesquels la configuration est activée tio.run. Exécuter en tant que programme complet avec entrée comme arguments.

val dit de réintégrer Monica
la source
1

Rubis , 78 67 octets

-11 octets grâce à @grawity.

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

Essayez-le en ligne!

L'entrée est un tableau de deux flottants.

Eric Duminil
la source
x.map{|v|[v].pack(?g).unpack(?N)[0]}x.pack("gg").unpack("NN")
user1686
@grawity: Génial, merci beaucoup! Cependant, le code est encore plus long qu'en Python. : - /
Eric Duminil
1

Java (JDK) , 109 76 octets

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

Essayez-le en ligne!

Cela fait un moment que je n'ai pas joué au golf à Java et je ne sais pas si j'ai besoin de la déclaration sur le LHS dans le cadre du décompte d'octets? S'il utilisait DoubleBinaryOperator, le LHS serait plus court, mais le RHS devrait utiliser Double.doubleToLongBits et Double.longBitsToDouble, donc c'est en fait plus long.

Merci à Neil pour une économie substantielle sur le nombre d'octets!

David Conrad
la source
1
IIRC vous n'avez même pas besoin de l'affectation dans le cadre du décompte d'octets, seulement dans le cadre de toute suite de tests que vous pourriez inclure dans votre Essayez-le en ligne! entête.
Neil
@Neil Merci! Cela fait une grosse différence!
David Conrad
0

Nettoyer , 36 octets

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

Essayez-le en ligne!

Heureusement, les types Realet Intsont de la même taille sur les plates-formes 64 bits ...
Malheureusement, nécessite une signature complète, sinon le graphique se transforme en bretzel et tout segfaults.

Οurous
la source