Als Eingabe erhalten Sie eine ganze Zahl k
im Bereich von -4503599627370496
(−2 52 ) bis 4503599627370496
(2 52 ). Wie allgemein bekannt , ganze Zahlen in diesem Bereich können Gleitkommazahlen als doppelte Genauigkeit repräsentieren genau werden.
Sie sollten Ausgabe das Hamming - Gewicht (Anzahl der Einsen) der Codierung von k
in binary64 Format . Dies verwendet 1 Bit für das Vorzeichen, 11 Bit für den Exponenten (mit einem Offset codiert) und 52 Bit für die Mantisse. Einzelheiten finden Sie unter dem obigen Link.
Als Beispiel wird Zahl 22
dargestellt als
0 10000000011 0110000000000000000000000000000000000000000000000000
Da es 5
solche gibt , ist die Ausgabe 5
.
Beachten Sie, dass Endianness das Ergebnis nicht beeinflusst. Sie können also die tatsächliche interne Darstellung von Werten mit doppelter Genauigkeit verwenden, um die Ausgabe zu berechnen.
Zusätzliche Regeln
- Programme oder Funktionen sind erlaubt.
- Es kann jede Programmiersprache verwendet werden.
- Standardlücken sind verboten
- Die eingegebene Nummer wird in Dezimalzahl angegeben. Ansonsten sind Ein- / Ausgabemittel und Format wie gewohnt flexibel .
- Kürzester Code in Bytes gewinnt.
Testfälle
22 -> 5
714 -> 6
0 -> 0
1 -> 10
4503599627370496 -> 5
4503599627370495 -> 55
1024 -> 3
-1024 -> 4
-4096 -> 5
1000000000 -> 16
-12345678 -> 16
quelle
binary64
wenn sie wollen? Einige Leute (einschließlich ich selbst) interpretierten die Frage so, dass Funktionen Eingaben als Integer-Typ wie C akzeptieren müssenlong
. In C können Sie argumentieren, dass die Sprache für Sie konvertiert wird, genau wie wenn Sie anrufensqrt((int)foo)
. Es gibt jedoch einige x86-Maschinencode-asm-Antworten (wie codegolf.stackexchange.com/a/136360/30206 und meine), die beide davon ausgehen, dass wir 64-Bit-Integer-Eingaben akzeptieren müssen. Das Akzeptieren einesbinary64
Wertes würde 5 Bytes sparen.binary64
als Ganzzahlen zur Basis 2 zu addieren . Wenn Sie sie trotzdem separat behandeln müssen, kann es sich lohnen, etwas anderes als Typ-Wortspiel zu tun und alle Bits in einer Schleife zu durchlaufen.long
, und konnten daher keine binary64-Anweisung verwendendouble
, da nicht alle Doubles Ganzzahlen sind. Aber alle ganzzahligendouble
s könnenlong
bis zu den Grenzen von in und zurück konvertiert werdenlong
. (Sie weisen darauf hin, dass das Gegenteil nicht zutrifft. Sie erhalten die nächstgelegene Darstellungdouble
, wenn Sie den Standardrundungsmodus annehmen.) Auf jeden Fall war dies eine absolut gültige Methode, um die Frage zu stellen. Ich habe es nur nicht sorgfältig gelesen>. <Antworten:
MATL , 5 Bytes
Probieren Sie es online!
Genaue Transliteration meiner MATLAB-Antwort. Beachten Sie, dass Eingabe und Ausgabe implizit sind. -2 Bytes dank Luis Mendo.
quelle
x86_64-Maschinensprache (Linux), 16 Byte
Akzeptiert einen einzelnen 64-Bit-Integer-Parameter in
RDI
, konvertiert ihn in einen Gleitkommawert inXMM0
, speichert diese Bits wieder inRAX
und berechnet dann das Hamming-Gewicht vonRAX
, wobei das Ergebnis in belassen wird ,RAX
damit es an den Aufrufer zurückgegeben werden kann.Erfordert einen Prozessor, der die
POPCNT
Anweisung unterstützt , beispielsweise Intel Nehalem, AMD Barcelona und spätere Mikroarchitekturen.Um es online auszuprobieren! , kompilieren Sie das folgende C-Programm und führen Sie es aus:
quelle
objdump -drwC -Mintel
zum Zerlegen in Intel-Syntax verwenden. Wenn Sie einen Zeiger in einem Register hätten, den Sie zum Speichern / Neuladen verwenden könnten, könnten Sie Bytes mitmovaps [rsi], xmm0
/ speichernpopcnt rax, [rsi]
. (movaps ist nur 3 Bytes, 2 kürzer als movq.) Aber das hilft hier nicht, weil[rsp-24]
2 zusätzliche Bytes benötigt werden (SIB, wenn RSP als Basis verwendet wird, plus disp8). Und diese zusätzlichen Bytes werden sowohl im Speicher als auch beim Neuladen benötigt. Na ja, ich dachte, ich sah eine Ersparnis, aber nein: /C (GCC) ,
8268 Bytes9 Bytes dank Neil.
böse Fließkomma-Bit-Level-Hacking
Probieren Sie es online!
quelle
;long l=
...;l*=2;)s+=l<0;
...long
. Es funktioniert unter x86-64 Linux, würde aber unter Windows fehlschlagen. Ich würde vorschlagen, "gcc mit 64-Bitlong
" zu sagen , da gcc auf vielen Plattformen läuft, viele davon mit unterschiedlichen ABIs.Python 3 ,
7271 Bytes1 Byte danke an Lynn.
Probieren Sie es online!
Erläuterung
Das binary64-Format besteht aus drei Komponenten:
1
wenn die Zahl negativ istquelle
n and(…)-(n>0)
ist ein Byte kürzer, nein?C (gcc) , 47 Bytes
Dies ist nicht portabel; Es wurde mit gcc 7.1.1 unter x86_64 unter Linux ohne Compiler-Flags getestet.
Probieren Sie es online!
quelle
long
nachdouble
an der Anrufstelle erledigt?n
inrax
mit nicht optimierten Code ist ziemlich geschmacklos. Es funktioniert nicht mehr, wenn Sie es aktivieren-O3
. Es ist also nicht nur gcc im Allgemeinen, sondern gcc auf x86-64 mit 64-Bitlong
und deaktivierter Optimierung. Wenn Sie all diese Anforderungen in Ihre Antwort aufnehmen, würde ich positiv stimmen. Ich gehe davon aus, dass es Plattformen gibt, die von gcc unterstützt werden und 64-Bit haben,long
aber daspopcountl
Ergebnis in einem anderen Register als dem Rückgabewertregister hinterlassen .double
es in Ordnung sein sollte , das Argument als zu akzeptieren . Es sagt nichts darüber aus, dass die Funktion es im base2-Format akzeptieren muss. Und ja, verschiedene Versionen von gcc könnten unterschiedlichen Code ausgeben, das ist auch wichtig. ( Unterhaltsame Tatsache: Ohne-mpopcnt
wird gcc daspopcnt
insn nicht verwenden und gibt eine Folge von Anweisungen aus, um es zu emulieren. Einige Architekturen haben überhaupt keine popcnt-Anweisung, müssen also__builtin_popcountl
immer eine Folge von insns verwenden.)__builtin_*
Funktionen haben Vorgängerversionen, um das Generieren illegaler Anweisungen zu vermeiden.-march=native
Verwendetpopcntq
nur, wenn es verfügbar ist.Java (OpenJDK 8) , 92 Byte
Probieren Sie es online!
quelle
C (gcc) 63 Bytes
Diese Lösung basiert auf der Antwort von @ LeakyNun, aber da er seine eigene Antwort nicht verbessern möchte, poste ich hier eine Golfversion.
Probieren Sie es online aus
quelle
C #,
817068 BytesSparen Sie 11 Bytes dank @Leaky Nun.
2 Bytes dank @Neil gespeichert.
Probieren Sie es online! Verwendet
System.BitConverter.DoubleToInt64Bits
anstelle desunsafe
Codes, da ich TIO nicht dazu bringen konnte, damit zu arbeiten.Voll / Formatierte Version:
quelle
for(;l!=0;l*=2)
und du brauchst nicht den Dreistoffs-=l>>31
?s+=l<0?1:0
?l
ist eine lange, so braucht ess-=l>>63
?Python 2 , 69 Bytes
-12 Byte, dank nur @ ASCII
Probieren Sie es online!
quelle
!
wird nicht benötigt, da die Bytereihenfolge hier keine Rolle spieltJavaScript (ES6),
818077 ByteBearbeiten: 1 Byte dank @Arnauld gespeichert. 3 Bytes gespart dank @DocMax.
quelle
g(i^i&-i,x++)
für -1 Byte tun ?new Float64Array([n])
durchFloat64Array.of(n)
x86-64-Maschinencode, 12 Byte für
int64_t
Eingabe6 Bytes für
double
EingabeBenötigt die
popcnt
ISA-Erweiterung (CPUID.01H:ECX.POPCNT [Bit 23] = 1
).(Oder 13 Bytes, wenn das Ändern des Arg an Ort und Stelle das Schreiben aller 64-Bits erfordert, anstatt Müll in den oberen 32 zu belassen. Ich denke, es ist vernünftig zu argumentieren, dass der Aufrufer wahrscheinlich nur die niedrigen 32b und x86 Null laden möchte -Erweitert sich implizit mit jeder 32-Bit-Operation von 32 auf 64. Trotzdem wird der Aufrufer davon abgehalten,
add rbx, [rdi]
etwas zu tun oder so.)x87-Anweisungen sind kürzer als die offensichtliche SSE2
cvtsi2sd
/movq
(in der Antwort von @ ceilingcat verwendet ), und ein[reg]
Adressierungsmodus ist so groß wie einereg
: nur ein mod / rm-Byte.Der Trick bestand darin, einen Weg zu finden, wie der Wert im Speicher übergeben werden kann, ohne dass zu viele Bytes für die Adressierungsmodi benötigt werden. (z. B. ist das Weitergeben des Stapels nicht so toll.) Glücklicherweise erlauben die Regeln Lese- / Schreib-Args oder separate Ausgabeargs , sodass ich den Aufrufer einfach dazu bringen kann, mir einen Zeiger auf den Speicher zu übergeben, den ich schreiben darf.
Aufrufbar von C mit der Signatur:
void popc_double(int64_t *in_out);
Nur die niedrigen 32b des Ergebnisses sind gültig, was für C vielleicht seltsam, für asm aber natürlich ist. (Um dies zu beheben, ist ein REX-Präfix im endgültigen Speicher (mov [rdi], rax
) erforderlich , also ein weiteres Byte.) Ändern Sie unter Windowsrdi
zurdx
, da Windows das x86-64-System-V-ABI nicht verwendet.NASM-Auflistung. Der TIO-Link enthält den Quellcode ohne Demontage.
Probieren Sie es online! Beinhaltet a
_start
Testprogramm, das ihm einen Wert übergibt und mit dem Rückgabewert exit status = popcnt beendet wird. (Öffnen Sie die Registerkarte "Debug", um sie anzuzeigen.)Das Übergeben separater Eingabe- / Ausgabezeiger würde ebenfalls funktionieren (rdi und rsi in der x86-64-SystemV-ABI), aber dann können wir die 64-Bit-Eingabe nicht vernünftigerweise zerstören oder die Notwendigkeit eines 64-Bit-Ausgabepuffers genauso einfach rechtfertigen, während nur die geschrieben wird niedrig 32b.
Wenn wir argumentieren möchten, dass wir einen Zeiger auf die ganze Zahl der Eingabe nehmen und sie zerstören können, während wir die Ausgabe zurückgeben
rax
, lassen Sie einfach dasmov [rdi], eax
from wegpopcnt_double_outarg
und bringen Sie es auf 10 Bytes herunter.Alternative ohne alberne Calling-Convention-Tricks, 14 Bytes
Verwenden Sie den Stapel als Arbeitsfläche,
push
um ihn dorthin zu bringen. Verwenden Siepush
/,pop
um Register in 2 Bytes anstelle von 3 für zu kopierenmov rdi, rsp
. ([rsp]
Benötigt immer ein SIB-Byte, es lohnt sich also, 2 Byte für das Kopieren auszugeben,rsp
bevor drei Anweisungen es verwenden.)Anruf von C mit dieser Signatur:
int popcnt_double_push(int64_t);
Eingabe im
double
Format übernehmenDie Frage besagt nur, dass es sich um eine Ganzzahl in einem bestimmten Bereich handelt und nicht, dass es sich um eine binäre Ganzzahldarstellung zur Basis 2 handeln muss. Das Akzeptieren von
double
Eingaben macht die Verwendung von x87 überflüssig. (Es sei denn, Sie verwenden eine benutzerdefinierte Aufrufkonvention, bei derdouble
s in x87-Registern übergeben wird. Anschließend in der roten Zone unter dem Stapel speichern und von dort aus einfügen.)11 Bytes:
Wir können jedoch den gleichen Trick wie zuvor verwenden, um eine 6-Byte-Version zu erstellen:
int pcd(const double&d);
6 Bytes .
quelle
Perl 5 ,
3332 + 1 (-p) =3433 Bytes1 Byte dank hobbs gespeichert
Probieren Sie es online!
quelle
d
ein Barewort (pack d,$_
anstelle vonpack"d",$_
)MATLAB, 36 Bytes
Verwenden der Tatsache, dass
de2bi
nicht nur kürzer alsdec2bin
, sondern auch ein Ergebnis in Einsen und Nullen anstelle von ASCII 48, 49 bereitgestellt wird.quelle
Java (64, 61, 41 Byte)
Ganz einfach mit der Standardbibliothek (Java SE 5+):
Beitrag von Kevin Cruijssen (Java SE 5+):
Beitrag von Kevin Cruijssen (Java SE 8+, Lambda-Funktion):
quelle
Long n
und usen.bitCount(...)
anstelle von verwendenLong.bitCount(...)
. Wenn Sie Java 8+ verwenden, können Sie außerdem aufn->n.bitCount(Double.doubleToLongBits(n))
( 41 Byte )Um einen anderen, sichereren Ansatz als den von TheLethalCoder zu versuchen , habe ich mir das ausgedacht (schade, dass C # so lange Methodennamen hat):
C # (.NET Core) , 76 + 13 Bytes
Probieren Sie es online!
Die Byteanzahl umfasst 13 Bytes für
using System;
. Zuerst muss ich dasdouble
in ein konvertierenlong
, das die gleiche binäre Darstellung hat, dann kann ich es in ein binäres konvertierenstring
, und dann zähle ich das1
s, indem ich den String aufspalte und die Teilstrings minus 1 zähle.quelle
using
in Ihre Byteanzahl aufnehmen.namespace System.Linq;{d=>Convert.ToString(BitConverter.DoubleToInt64Bits(d),2).Count(c=>c>48)}
. Obwohl ich es nicht getestet habe, sollte es funktionieren.using
Direktive hinzufügen musste .namespace
es praktisch ist. Aber ja, in diesem Fall war es etwas billiger, Linq zu meiden. Wollte nur mit seiner Herangehensweise kommentieren, falls Sie Ideen hatten, wie man es verkürzen kann, um Ihnen Bytes zu sparen.Sum(c=>c&1)
ist kürzer. OderSum()-768
Jelly , 19 Bytes
Probieren Sie es online!
quelle
Gleichstrom, 79 Bytes
Die Ausgabe bleibt oben auf dem Stapel.
Ich werde später eine Erklärung hinzufügen.
Probieren Sie es online!
Beachten Sie, dass negative Zahlen durch vorangestellt sind
_
, nicht-
.quelle
Groovy (mit Parrot-Parser) , 46 Byte
quelle
C 67 Bytes
Kontrollcode und Ergebnisse
quelle
Erlang 55 Bytes
Eine anonyme Funktion, die alle
1
s in einer Zahl zählt, die als 64-Bit-Float codiert ist.Verweise:
quelle