Uhm, het ltrimmen van je most significant bits lijkt mij geen goed idee?
En als dat zou kloppen, hoe zou dat dan moeten werken?
En waar komt vermenigvuldigen met -1 vandaan?!
De negatie van een bitreeks verkrijg je door de bits te flippen, dit kun je (o.a.) met de tilde-operator (~ - de NOT-operator) doen. Wat heeft een min-teken hier mee te maken?
Dit is overigens geen XOR, want de XOR operator (^) werkt op twee operanden.
Over spraakverwarring en slecht lezen gesproken :/.\
EDIT: om terug te komen op je oorspronkelijke vraagstelling:
As PHP's integer type is signed, but dechex() deals with unsigned integers, negative integers will be treated as though they were unsigned.
Dat is mogelijk een verklaring voor het gedrag wat je ervaart wanneer je een negatief getal voert aan dechex().
EDIT #2: bij negatieve getallen hangt het wellicht ook van de precisie van het getaltype af wat het 2s complement is, dus eigenlijk kun je bij negatieve getallen niet zeggen wat het (bijbehorende) 2s complement is? Het lijkt mij handiger om alleen positieve getallen te accepteren, of om voor te schrijven wat dan de precisie zou moeten zijn?
EDIT #3: okay, na wat experimenteren lijkt mij dit een degelijke aanpak: het handigste is om gewoon alles naar een binaire schrijfwijze te converteren. Vervolgens zet je een bitmasker in in combinatie met XOR om de bits te inverteren. En tot slot tel je hier (weer in het decimale stelsel) 1 bij op. Vervolgens retourneer je het resultaat in de gewenste base-x notatie, in jouw geval hexadecimaal (het 16-tallige stelsel). Jouw functie wordt dus zoiets als:
<?php
function twosComplementHex($hex) {
$binary = base_convert($hex, 16, 2); // from hex to binary
$mask = str_repeat('1', strlen($binary)); // bitmask for inverting bits
$not = bindec($binary) ^ bindec($mask); // XOR bits, basically inverting bits of input
return base_convert($not + 1, 10, 16); // add 1 and return result as hex
}
echo twosComplementHex('e2'); // levert '1e'
?>
Maar wellicht loont het de moeite om dit wat verder door te testen.
Uhm, het ltrimmen van je most significant bits lijkt mij geen goed idee?
En als dat zou kloppen, hoe zou dat dan moeten werken?
Dit kwam uit het andere voorbeeld.
En waar komt vermenigvuldigen met -1 vandaan?!
De negatie van een bitreeks verkrijg je door de bits te flippen, dit kun je (o.a.) met de tilde-operator (~ - de NOT-operator) doen. Wat heeft een min-teken hier mee te maken?
ik begreep dat 2's complement de negatieve versie was van hetzelfde getal. Dus 1 / -1 , 4 / -4 etc. dus vandaar.
EDIT: om terug te komen op je oorspronkelijke vraagstelling:
[quote]As PHP's integer type is signed, but dechex() deals with unsigned integers, negative integers will be treated as though they were unsigned.
Dat is mogelijk een verklaring voor het gedrag wat je ervaart wanneer je een negatief getal voert aan dechex().
EDIT #2: bij negatieve getallen hangt het wellicht ook van de precisie van het getaltype af wat het 2s complement is, dus eigenlijk kun je bij negatieve getallen niet zeggen wat het (bijbehorende) 2s complement is? Het lijkt mij handiger om alleen positieve getallen te accepteren, of om voor te schrijven wat dan de precisie zou moeten zijn?
[/quote]
EDIT #3: okay, na wat experimenteren lijkt mij dit een degelijke aanpak: het handigste is om gewoon alles naar een binaire schrijfwijze te converteren. Vervolgens zet je een bitmasker in in combinatie met XOR om de bits te inverteren. En tot slot tel je hier (weer in het decimale stelsel) 1 bij op. Vervolgens retourneer je het resultaat in de gewenste base-x notatie, in jouw geval hexadecimaal (het 16-tallige stelsel). Jouw functie wordt dus zoiets als:
<?php
function twosComplementHex($hex) {
$binary = base_convert($hex, 16, 2); // from hex to binary
$mask = str_repeat('1', strlen($binary)); // bitmask for inverting bits
$not = bindec($binary) ^ bindec($mask); // XOR bits, basically inverting bits of input
return base_convert($not + 1, 10, 16); // add 1 and return result as hex
}
echo twosComplementHex('e2'); // levert '1e'
?>
Maar wellicht loont het de moeite om dit wat verder door te testen.
Ok, en waarom gebruik je nu XOR ipv de ~ operator? Verder is het wel een duidelijk functie bedankt voor alle uitleg. Binaire rekenen is lang geleden voor me merk ik.
ik begreep dat 2's complement de negatieve versie was van hetzelfde getal. Dus 1 / -1 , 4 / -4 etc. dus vandaar.
Mja, maar je bent stiekem bezig met signed getallen, dus wat -4 is hangt waarschijnlijk af van de maximale lengte van zo'n getal in het geheugen. -4 ziet er op de ene pjoeter anders uit dan op een ander pjoeter.
EDIT: het hangt er ook een beetje vanaf hoe je jouw hexadecimale getallen gaat gebruiken. Het 2s complement van een getal is mogelijk dubbelzinnig, of liever gezegd, is mogelijk niet altijd hetzelfde? Op grond waarvan is in jouw geval het 2s complement van e2 altijd 1e?
Deze zut is voor mij ook te lang geleden :p.
Ok, en waarom gebruik je nu XOR ipv de ~ operator?
Omdat de NOT-operator niet lijkt te werken op binaire noch hexadecimale getallen (of liever gezegd strings, een bitreeks is gewoon een string blijkbaar volgens var_dump()). Als ik de NOT pak van de binaire of hexadecimale variant van E2 dan rollen er allemaal arabische karakters uit. Dit omdat er dan karakters worden geïnverteerd in plaats van bits. Voor het correct werken met de XOR operator heb ik weer wel getallen nodig.
Merk op dat een XOR met een bitmask effectief hetzelfde doet als de NOT, omdat de waarheidstabellen van A XOR B en NOT A hetzelfde zijn. Ik werk dus wel met een XOR, maar het is in feite een NOT operatie.
A B A XOR B NOT A
0 1 1 1
1 1 0 0
Hierbij is A het bit onder beschouwing en B je bitmask (altijd 1).
(dit stond in wezen al in het commentaar van de code: bitmask for inverting bits en XOR bits, basically inverting bits of input, maar hier alsnog het bewijs hiervoor :p)