I am struggling on how to create a function that converts a number into binary and then back. I know there is a built-in function about this BaseForm[]
but I am trying not to use it.
I started thinking about using the RealDigits[]
but I don't really know where to go from here. I will keep trying and post any code I do.
If anyone can help me with this I would be really grateful. Thanks.
2 Answers
Just to illustrate ways to do you own way:
Binarize integer:
binary[n_] :=
Reverse@NestWhileList[
QuotientRemainder[#[[1]], 2] &, {n}, # != {0, 0} &][[2 ;; -2, 2]]
This produces a list, e.g. binary[23]
yields: {1, 0, 1, 1, 1}.
You can invert:
frombinary[n_] :=
With[{k = Length[n]}, n . PowerRange[2^(k
- 1), 1, 1/2]]
If you want create output like BaseForm
:
bf[n_] := Subscript[Row[binary[n]], 2]
You can invert this by accessing list, e.g.
bf2d[n_] := frombinary[(n[[1, 1]])]
where input is Subscript[Row[...]]
,
The in-built functions are optimized. I present this to motivate "create your own" play.
Update/Edit
In response to comment:
binary[n_] :=
Reverse@NestWhileList[
QuotientRemainder[#[[1]], 2] &, {n}, # != {0, 0} &][[2 ;; -2, 2]]
binary[0] = {0};
dec[n_] :=
NestWhileList[
Reverse@MixedFractionParts[2 #[[1]]] &, {n}, # != {0,
0} &][[2 ;; -2, 2]]
anybin[n_] :=
Module[{i = IntegerPart[n], f = FractionalPart[n]},
Subscript[Row[Join[binary[i], {"."}, dec[f]]], 2]]
Comparing with BaseForm:
Table[{j, BaseForm[j, 2],
anybin[j]}, {j, {0.5, 1.25, 3.75, 1.2, 0.13}}] //
TableForm[#, TableHeadings -> {None, {"n", "BaseForm","anybin"}}] &
Noting: fractions such as 1/5 do not have binary finite representations.
e.g.
Sum[2^(-4 j + 1) + 2^(- 4 j), {j, 1, 3}] // N
Limit[Sum[2^(-4 j + 1) + 2^(- 4 j), {j, 1, x}], x -> Infinity]
They are recurring. This could truncated to show repeating sequence. I leave that to enthusiast.
-
$\begingroup$ It's a (+1) from me, but a relevant comment: the
binary[0.13]
does not work and this was pointed out by the author of the OP under my reply in the comments. Perhaps you'd like to update your answer $\endgroup$– bmfApr 9, 2022 at 4:43 -
$\begingroup$ @bmf thank you. I apologize for not reading OP question well enough. As I wrote in answer "Binarize integer". However, I take your point. $\endgroup$– ubpdqnApr 9, 2022 at 4:46
-
$\begingroup$ yes, of course I understand. And my comment was only meant to serve as hint for an improvement. I do find your answer very good indeed :) $\endgroup$– bmfApr 9, 2022 at 4:48
Edit: addressing the comment
Updated code is:
test[xx_, digits_: 17] := If[xx >= 1,
ToString@Row@Insert[#1, ".", #2 + 1] & @@
RealDigits[xx, 2, digits],
ToString@Row@
Join[{0},
Insert[Join[
ConstantArray[0, Abs[RealDigits[xx, 2, digits][[2]]]],
RealDigits[xx, 2, digits][[1]]], ".", 1]]]
Checks:
Original answer below:
To binary
tobinary[realnum_] :=
ToString@Row@Insert[#1, ".", #2 + 1] & @@ RealDigits[#, 2] &[realnum]
And we have
Table[tobinary[ii], {ii, 0, 4, 1}]
which can be compared with
Table[BaseForm[i, 2], {i, 0, 4}]
Works also for
tobinary[17.27]
From binary
frombinary[mynumber_] := FromDigits[RealDigits[mynumber], 2]
Quick check:
frombinary[100]
And works also for
frombinary[10001.010001010001111010111000010100011110101110000101] //
N
-
$\begingroup$ Thanks. Is there a way for it to work for lowers decimals? Because when I try using for example 0.23 it doesn't work. Thanks $\endgroup$– peter21Apr 5, 2022 at 21:18
-
$\begingroup$ @peter21 you might want to look at the edited version. The key was to understand the output of
RealDigits[0.21, 2, 11]
$\endgroup$– bmfApr 5, 2022 at 22:40 -
$\begingroup$ @peter21 so, does the updated version work as you were expecting? $\endgroup$– bmfApr 7, 2022 at 3:38
-
-
IntegerDigits[]
andFromDigits[]
, but if this is homework, then it probably asks you to calculate the digits not using the built-in functions. In this case, you will probably wantMod[m,n]
(modulo operation, reminder) andFloor[m/n]
(integer part after the division). $\endgroup$