9
$\begingroup$

I am working with hexadecimal bytes but need to shift them into lists of binary bits for a few operations and then back again.

For example, I would like C12B to turn into {1,1,0,0,0,0,0,1,0,0,1,0,1,0,1,1} for evaluations, so BaseForm[c12b,16] is out of the question for me, as far as I can tell.

Trying IntegerDigits[16^^C12B,2] gets me what I need, but my problem is if I try to store the hex value as a variable for use in a function.

Let's say I have a code:

hexToBinary[hexstring_]:=
Return[IntegerDigits[16^^hexstring,2]];

I realize I am no expert programmer, so there are probably small issues with this I cannot foresee, but 16^^hexstring won't evaluate, as it thinks "hexstring" is the number I am trying to evaluate and tells me the letters are too large for that number base. Additionally, the set delayed fails to work in this case, and the cell evaluates immediately, returning the error just described. In fact, hexstring never turns green inside the IntegerDigits part.

I ran Print[Head[c12b]] earlier, and Mathematica told me it's treating this as a "symbol." I found out that if I input the hex in the form 0xc12b, Mathematica now thinks it's an integer, but this doesn't solve my problem of saving the value to a variable and then taking 16^^variable.

Is there any feasible way around this? I am also going to have to turn the binary list back to Hex at some point, and I imagine I will run into similar problems on that end, but I have not gotten that far yet.

EDIT: If I make a function like Hausdorff suggested:
hexToBinary[hexstring_String] := IntegerDigits[FromDigits[hexstring,16],2];
Then that fixes my problem if and only if the hex value is put into this function as a string that has been saved under a variable, like:
input="c12b", followed by hexToBinary[input]. But part of my question still exists: is there a way to save the hex value as an integer variable, like input=c12b? Mathematica thinks c12b is another variable I have not yet defined if I try this.

The reason I ask this is not because I'm too lazy to put quotes around the strings but because I wanted to know if there is any way to do exactly what has been done here but without inputting it as a string in quotation marks. If I have to have the quotation marks, then so be it! The solution hints so far have been life-saving.

$\endgroup$
5
  • 2
    $\begingroup$ IntegerDigits[FromDigits["C12B", 16], 2] $\endgroup$ Commented Jul 18, 2020 at 22:46
  • $\begingroup$ What exactly do you want to to do with the hex representation? Mathematica will interpret c12b as a variable (you saw yourself that Print[Head[c12b]] was Symbol), which is why the special format using ^^ exists. However, Mathematica will store any hex number you input this way as a normal integer internally. $\endgroup$
    – Hausdorff
    Commented Jul 19, 2020 at 8:07
  • $\begingroup$ I have a function that requires two hexadecimal inputs, and unless I wrap them in quotes to force them in as strings, there doesn't seem to be any way to just allow my users to type their hexadecimal numbers. Since that is relying on the user to input the correct values, I thought it would be wiser to see if there was a way around using the quotation marks. But my current implementation has your method coupled with the user inputting their two hex values directly into "" to get string format. $\endgroup$ Commented Jul 20, 2020 at 14:27
  • $\begingroup$ So, my current implementation is: text1=IntegerDigits[FromDigits["YOURHEX1HERE",16],2]; text2=IntegerDigits[FromDigits["YOURHEX2HERE",16],2]; Function[text1,text2]; all in the same cell so they are evaluated simultaneously and the hex values are forced in in the proper format. I was trying to see if there was a way to just have my users do a Function[YOURHEX1HERE,YOURHEX2HERE] without causing a cascade of problems. $\endgroup$ Commented Jul 20, 2020 at 14:28
  • $\begingroup$ You could pass the input through ToString first. I just edited my answer with an example. $\endgroup$
    – Hausdorff
    Commented Jul 20, 2020 at 22:08

2 Answers 2

11
$\begingroup$

You cannot use the notation 16^^ with variable arguments, since it does not get "evaluated" like normal functions, but rather it is just a way of writing integers in different bases. For more information you can look at this question.

A way to implement what you want would be

hexToBinary[hexstring_String] := IntegerDigits[FromDigits[hexstring,16],2];

To turn the list of binaries back into hex, you could use

binaryToHex[binary_List] := IntegerString[FromDigits[binary,2],16];

So

hexToBinary["c12b"]
{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1}
 binaryToHex[{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1}]
"c12b"

EDIT

As a workaround to allow simple user input you could use

hexToBinary[hex_] /; StringMatchQ[ToString[hex],RegularExpression["[A-Fa-f0-9]*"]] := 
    IntegerDigits[FromDigits[ToString@hex,16],2];

hexToBinary[c12b]
{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1}

Of course, this could cause problems if for example someone feeds in an already defined variable, but the StringMatchQ should prevent at least some of them.

$\endgroup$
2
  • $\begingroup$ Thank you very much for the prompt reply. I added an edit to the original to dig a bit deeper, if you have any additional insight. $\endgroup$ Commented Jul 19, 2020 at 1:15
  • $\begingroup$ Thanks for the edit! That's great! $\endgroup$ Commented Jul 21, 2020 at 0:35
4
$\begingroup$

FromDigits is fast but it does not catch invalid inputs.

IntegerDigits[FromDigits["C12BZ", 16], 2]

{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1}

Interpreter is slower but it will balk at invalid inputs.

IntegerDigits[Interpreter["HexInteger"]["C12BZ"], 2]

enter image description here

$\endgroup$
1
  • $\begingroup$ I appreciate your help. Thank you for the prompt reply. Fortunately, I will be taking care of invalid inputs on the front end before this, so that shouldn't be a problem for me, I hope. I added an edit to the original to dig a bit deeper, if you have any additional insight. $\endgroup$ Commented Jul 19, 2020 at 1:16

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.