Convert from base 10 to base 2 without built-in base conversions

16

3

Background:

You have been given an assignment to convert base 10 numbers to base 2 without using any premade base conversion functions. You can't use any imported libraries either.

Problem:

Convert an input string from base 10 (decimal) to base 2 (binary). You may not use any premade base conversion code/functions/methods, or imported libraries. Since this is , the shortest answer in bytes will win.

Input will be anything from -32768 to 32767 (include sign byte handling in your code)

TheDoctor

Posted 2014-02-16T00:31:40.303

Reputation: 7 793

3Q: what does "sign byte handling" mean - shall I output "-xxxx" for a negative number? Then some of us are wrong, incl. me, as I output "11...11" for -1 (aka as unsigned) – blabla999 – 2014-02-16T02:19:19.463

Sign byte handling - the MSB of signed variables controls if they are negative – TheDoctor – 2014-02-16T03:12:10.650

1sure, but do I have to >print< them as sign '-' followed by magnitude? – blabla999 – 2014-02-16T03:14:39.160

@blabla999 - No you don't – TheDoctor – 2014-02-16T03:34:44.710

3the MSB of signed variables controls if they are negative - that sounds like sign bit, however as the range -32768..32767 suggests, you want 2's complement. So which do you want?.. – mniip – 2014-02-16T12:03:24.693

The range suggests i want you to be able to do 16-bit signed numbers, and yes, 2's compliment is essentially my definition of sign bit. – TheDoctor – 2014-02-16T14:31:24.617

Answers

4

GolfScript - 17 bytes

~{.1&\2/}16*;]-1%

Not too much more verbose than the built-in ~2base.

primo

Posted 2014-02-16T00:31:40.303

Reputation: 30 891

1I don't know golfscript but a few sample runs lead me to conclude that you should remove the ~ – user12205 – 2014-02-16T22:10:39.123

@ace Because the initial input is a string "37", for example, the operation "37" & 1 (in infix) is a set-wise operation. The ~ at the front converts the input to an integer. – primo – 2014-02-17T02:38:04.637

I did my test here http://golfscript.apphb.com/?c=I1RoaXMgaXMgYSBzYW1wbGUgcHJvZ3JhbSB0byBkZXRlcm1pbmUgdGhlIEdyZWF0ZXN0IENvbW1vbiBEaXZpc29yIG9mIHR3byBudW1iZXJzCgojVGhlIGFyZ3VtZW50czoKMTAKCiNUaGUgcHJvZ3JhbToKfnsuMSZcMi99MTYqO10tMSU%3D does this mean this interpreter is incorrect? (Sorry I really know nothing about golfscript)

– user12205 – 2014-02-17T08:19:05.487

2

The interpreter is correct; because you've pushed the integer value 10 onto the stack, it is not necessary to evaluate it. However, when read from stdin, the input will be a string (test here). The problem description also explicitly states that the input is a string.

– primo – 2014-02-17T08:27:43.087

12

JavaScript, 46

for(x=prompt(o='');x;x>>>=1)o=(x&1)+o;alert(o)

copy

Posted 2014-02-16T00:31:40.303

Reputation: 6 466

bitwise always amazing – NTCG – 2018-07-15T22:00:00.680

Lol, I didn't even know that a 4-character operator (>>>=) existed! +1 (Also, if you run it in the console, you can save the last 9 characters.) – Doorknob – 2014-02-16T03:53:26.297

1It's not 4-characters, it's two operators: the >>> is the 0-filling bitwise right shift, followed by an assignment. Try: x=8; x>>>=1; x; and x=8; x>>>1; x; -- in the first case, the value of x has changed; in the second, it has not. – Graham Charles – 2014-02-16T09:03:40.977

3

@GrahamCharles >>>= is a single operator.

– primo – 2014-02-16T13:43:12.520

Well, look at that! Thanks, @primo... you learn something every day! – Graham Charles – 2014-02-17T23:52:52.003

Save 1 character by using +=: for(x=prompt(o='');x;x>>>=1)o+=(x&1);alert(o) – ComFreek – 2014-02-19T18:29:55.607

2@ComFreek That would reverse the order of the digits – copy – 2014-02-19T18:39:05.947

@copy Oh, you're right, my bad. Have a +1 ;) – ComFreek – 2014-02-19T18:42:26.930

4

Brainf*ck, 98 77

Obviously this isn't for the purpose of winning but what would a competition be if it didnt have a brainfk solution

++++[>++++<-]>>,<[->>++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]++++++[->++++++++<]>.[-]>[-<<<+>>>]<<<<]

Since brainfk can only handle 8bit integers and no negatives I guess it doesn't fully abide by the rules but hey I was never in it to win it.

This actually does work for 16-bit input if your interpreter supports

I even got it to output in ascii values

Here is the annotated code:

++[>++++<-]                       preload 8 onto cell 1
>>,<                                input into cell 2
[-                                  iterate over cell 1
    >>++<                               put 2 in cell 3
    [->-[>+>>]>[+[-<+>]>+>>]<<<<<]      division algorithm: converts {n d} into {0 d_minus_n%d n%d n/d}
    >[-]++++++[->++++++++<]>           clears cell 4 and puts 48(ascii of 0) into cell 5
    .[-]                                output n%2 and clear it (the bit)
    >[-<<<+>>>]                         bring n/2 into cell 2 (to be used for division in next iteration)
<<<<]                               end iterate

Shorter algorithm (77):

+>,>-<[>>[->]++[-<+]-<-]++++++++[->++++++<]>+[->+>+>+>+>+>+>+>+<<<<<<<<]>[.>]

This one can only handle 8bit integers.

The algorithm works by using a binary counter which is actually very short (one increment is >[->]++[-<+]-<- which then lays out the bits. The issue is that it is difficult to print out all of the bits

That last algorithm can be adapted to fit any number of bits at the expense of bytes. To be able to deal with N bit integers, it requires 53+3*N bytes to encode.

examples:

(1 bit) +>,>-<[>>[->]++[-<+]-<-]++++++++[->++++++<]>+[->+<]>[.>]
(2 bit) +>,>-<[>>[->]++[-<+]-<-]++++++++[->++++++<]>+[->+>+<<]>[.>]
(3 bit) +>,>-<[>>[->]++[-<+]-<-]++++++++[->++++++<]>+[->+>+>+<<<]>[.>]
etc

ASKASK

Posted 2014-02-16T00:31:40.303

Reputation: 291

3

Mandatory APL answer - 21 22

"01"[1+2|⌊⎕÷2⋆⊖0,⍳15]

Examples:

      "01"[1+2|⌊⎕÷2⋆⊖0,⍳15]
⎕: 0
0000000000000000
      "01"[1+2|⌊⎕÷2⋆⊖0,⍳15]
⎕: 13
0000000000001101
      "01"[1+2|⌊⎕÷2⋆⊖0,⍳15]
⎕: 9999
0010011100001111
      "01"[1+2|⌊⎕÷2⋆⊖0,⍳15]
⎕: -3
1111111111111101
      "01"[1+2|⌊⎕÷2⋆⊖0,⍳15]
⎕: 32767
0111111111111111

mniip

Posted 2014-02-16T00:31:40.303

Reputation: 9 396

You can reduce with almost 50% by using ⎕IO←0, and returning an array of bits instead of a string: 2|⌊⎕÷2*⊖⍳16. – Adám – 2016-06-18T23:09:03.817

3

Turing Machine Code, 272 bytes

As usual, I'm using the rule table syntax defined here. You can test it on that site or, alternatively, using this java implementation.

A lot of the code is copied from my decimal-to-hex converter here.

0 * * l B
B * * l C
C * 0 r D
D * * r E
E * * r A
A _ * l 1
A * * r *
1 0 9 l 1
1 1 0 l 2
1 2 1 l 2
1 3 2 l 2
1 4 3 l 2
1 5 4 l 2
1 6 5 l 2
1 7 6 l 2
1 8 7 l 2
1 9 8 l 2
1 _ * r Y
Y * * * X
X * _ r X
X _ _ * halt
2 * * l 2
2 _ _ l 3
3 * 1 r 4
3 1 0 l 3
4 * * r 4
4 _ _ r A

Counts down from the input in base 10 while counting up from 0 in base 2. On decrementing zero, it erases the input block and terminates.

SuperJedi224

Posted 2014-02-16T00:31:40.303

Reputation: 11 342

2

Javascript 59

o='';i=parseInt(prompt());do{o=(i&1)+o}while(i>>=1)alert(o)

Michael M.

Posted 2014-02-16T00:31:40.303

Reputation: 12 173

You can use +x instead of parseInt(x) – Cyoce – 2016-08-07T17:01:33.430

2

Perl, 44

This is my first Perl program ever, so please forgive me if this can be easily golfed down further. Edit: Thank you @primo for taking 7 chars away from my answer.

$x=<>;do{@s=($x&1,@s)}while($x>>=1);print@s

$x=<>;do{push@s,$x&1}while($x>>=1);print reverse@s

The logic is essentially the same as my previous C solution.

Also, uses 64 bits.

user12205

Posted 2014-02-16T00:31:40.303

Reputation: 8 752

1You can save the reverse by constructing the array backwards: @s=($x&1,@s). – primo – 2014-02-16T02:52:23.443

1Now that the contest is over, the best I found was 34: $\=$_%2 .$\while$_=$_>>1||<>;print. Or, if command line options count one byte each, 27: 1while$\=$_%2 .$\,$_>>=1}{ using -p. – primo – 2014-02-20T14:22:16.927

2

Javascript - 56 48 and 36 28 characters

  • Does not works with negative numbers.

Thanks to @Blender for shaving 8 characters.

This form takes input and shows output, 48 characters:

x=prompt();for(a="";x;x=~~(x/2))a=x%2+a;alert(a)

If just an instruction that puts in a variable a the binary form of a variable x is needed (and you don't bother in destroying the x value as a side-effect), here it is with 28 characters:

for(a="";x;x=~~(x/2))a=x%2+a

Victor Stafusa

Posted 2014-02-16T00:31:40.303

Reputation: 8 612

1You can replace Math.floor with ~~, as the range for the numbers is small. – Blender – 2014-02-16T11:53:41.470

@Blender Thanks, I knew that there existed some way, just could not find it. – Victor Stafusa – 2014-02-16T12:01:50.347

@Victor I don't know javascript so I might be wrong but at the end when you say a=x%2+a could this be shortened to a+=x%2 ? It works in all languages I know. – Albert Renshaw – 2014-02-16T23:10:53.177

@AlbertRenshaw No, This would be the same as a=a+x%2, but that + is for string concatenation. I.e, your suggestion results in the digits in the backwards order. – Victor Stafusa – 2014-02-17T01:55:54.303

@Victor Ah! Thankyou! – Albert Renshaw – 2014-02-17T03:02:50.617

2

C, 55 chars

Prints an extra leading zero (for the sake of 2 bytes).
Recursion within printf reverses the print order, so the algorithm extracts bits right-to-left but prints left-to-right.

EDIT: Saved a char by using putchar instead of printf.

f(x){(x*=x<0?-printf("-"):1)&&f(x/2);putchar(48+x%2);}

ugoren

Posted 2014-02-16T00:31:40.303

Reputation: 16 527

2

Python - 61 60 characters

x=input();print"".join("01"[x>>i&1]for i in range(15,-1,-1))

C0deH4cker

Posted 2014-02-16T00:31:40.303

Reputation: 352

if you call it from the command-line you could leave aside print as it automatically returns the result – paul.oderso – 2016-08-18T13:14:35.793

2You can get rid of the space between print and "". – Blender – 2014-02-16T11:54:32.130

@Blender I was just about to suggest the same thing :) – Albert Renshaw – 2014-02-16T23:13:48.833

@Blender Ha true, didn't even notice. Done! – C0deH4cker – 2014-02-17T03:54:49.273

2

Dyalog APL, 11 bytes

2|⌊⎕÷2*⌽⍳16

2| The division remainder when halved of
the rounded down value of
the input
÷ divided by each of
2* two to the power of each of
⍳16 {0, 1, 2, ..., 15}

Requires ⎕IO←0 which is default on many systems.

TryAPL online!

Adám

Posted 2014-02-16T00:31:40.303

Reputation: 37 779

1

PowerShell, 59 87 82 70 bytes

+28 bytes for supporting negative numbers.
-12 bytes thanks to @ASCII-only

param($d)$m=$d-lt0;while($d){$n="01"[$d%2]+$n;$d=($d-$d%2)/2}'-'*$m+$n

Try it online!

Adapted from this code. Takes input through a commandline parameter -d.

Gabriel Mills

Posted 2014-02-16T00:31:40.303

Reputation: 778

What about numbers with sign? – mazzy – 2019-03-10T05:46:42.897

73? – ASCII-only – 2019-03-11T03:09:54.893

so close, yet so far. also close – ASCII-only – 2019-03-11T03:14:37.943

oh wait 70

– ASCII-only – 2019-03-11T03:22:05.767

1

APL(NARS), 17 chars, 34 bytes

{2∣⌊⍵÷2*(⍺-1)..0}

It is a copy and modify of Adam answer https://codegolf.stackexchange.com/a/90107 in the way one can add the parameter for the bits lenght, and ⎕IO for this function (here is ⎕IO=1) should have no importance...

  f←{2∣⌊⍵÷2*(⍺-1)..0}
  16 f 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 
  32 f 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 
  32 f ¯1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
  16 f ¯1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
  64 f ¯12345678
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 1 1 0 0 1 1 1 1 0 1 0 1 1 0 0 1 0 

it seeme easy handle the number of bits in this way (I cheked that last result should be right)

RosLuP

Posted 2014-02-16T00:31:40.303

Reputation: 3 036

1

C, 81

char b[17];i=15;main(x){scanf("%d",&x);while(i+1)b[i--]=(x&1)+48,x>>=1;puts(b);}

The output has strictly 16 bits (including padding zeros)

user12205

Posted 2014-02-16T00:31:40.303

Reputation: 8 752

1

Apps Script + Google Sheets, 147 144 121 bytes

Script

function j(decNumb){var str='';do{str=String(decNumb%2)+str;decNumb=decNumb/2|0;}while(decNumb>=1);return parseInt(str);}

Sheet

=j(b1)

Modified version of this script by ZygD.

weatherman115

Posted 2014-02-16T00:31:40.303

Reputation: 605

Can you remove any spaces? – NoOneIsHere – 2016-06-16T20:06:22.207

1

Haskell, 66 bytes

c 0=0
c n=c(div n 2)*10+mod n 2
b('-':r)='-':b r
b r=show.c.read$r

Call with b "-1023", add main=interact b for a complete program or try it on Ideon.

c performs the conversion for positive integers.
b r=show.c.read$r converts a string to a number, applies c and converts back to string.
b('-':r)='-':b r strips a possible leading - and re-appends it to the result.

Laikoni

Posted 2014-02-16T00:31:40.303

Reputation: 23 676

0

Java 8, 80 71 bytes

n->{String r="";for(int i=n<0?-n:n;i>0;i/=2)r=i%2+r;return n==0?"0":r;}

-9 bytes due to a rule in the comments.. Negative base-10 inputs may return the positive/absolute base-2 value as output apparently.

Explanation:

Try it online.

n->{                   // Method with integer parameter and String return-type
  String r="";         //  Result-String, starting empty
  for(int i=n<0?-n:n;  //  Start `i` at the absolute (non-negative) value of the input
      i>0;             //  Loop as long as `i` is not 0
      i/=2)            //    After every iteration: integer-divide `i` by 2
    r=i%2+r;           //   Prepend the result with `i` modulo-2
  return n==0?         //  If the input is 0:
          "0"          //   Return literal "0"
         :             //  Else:
          r;           //   Return the result-String

Kevin Cruijssen

Posted 2014-02-16T00:31:40.303

Reputation: 67 575

0

Small Basic, 133 bytes

A script that inputs from and outputs to the TextWindow console.

n=TextWindow.Read()
While n>0
c=c+1
x[c]=Math.Remainder(n,2)
n=Math.Floor(n/2)
EndWhile
For i=0To c-1
TextWindow.Write(x[c-i])
EndFor

Try it at SmallBasic.com Requires Silverlight and thus must be run in IE.

I/O is taken/given from the black console.

-22 bytes thanks to @Neil

Taylor Scott

Posted 2014-02-16T00:31:40.303

Reputation: 6 709

Can you not use For i=0To c-1? – Neil – 2018-07-13T20:57:42.833

@Neil - I absolutely can. Great catch! – Taylor Scott – 2018-07-15T21:01:15.447

0

C (gcc), 50 43 bytes

-7 bytes thanks to ceilingcat.

f(n){printf("-%d"+(~n?n&&f(n/2),1:0),n&1);}

Try it online!

gastropner

Posted 2014-02-16T00:31:40.303

Reputation: 3 264

@ceilingcat Cheers! – gastropner – 2018-08-04T04:48:04.987

0

Kotlin, 82 bytes

{s:String->{var i=s.toInt()
var r=""
(0..15).map{r="${i and 1}$r"
i=i shr 1}
r}()}

Try it online!

JohnWells

Posted 2014-02-16T00:31:40.303

Reputation: 611

0

MATL, 15 17 bytes

t0<?16Ww+]`2&\t]x

Try it on MATL Online

TIO

(+2 bytes removing leading 0 for negative numbers, sign bit should be the first bit.)

Output on MATL Online should be read bottom-up (MSB is at the bottom).

The main part is pretty simple: `2&\t = while the value is greater than 0, divide by 2 and accumulate the remainders.

Handling negative numbers and giving them 2's complement representation was the tricky part. In the end I went with the "subtract from \$ 2^N \$" method of getting a number's two's complement. Since we're only required to handle values upto -32768, for negative numbers the code creates \$ 2^{16} = 65536 \$ with 16W, adds the input to that (eg. 65536 + (-42)), which gives something MATLAB sees as a positive number but represents the input's signed binary representation in 16-bit form.

sundar - Reinstate Monica

Posted 2014-02-16T00:31:40.303

Reputation: 5 296

0

PowerShell, 43 bytes

param($n)15..0|%{$r+='01'[($n-shr$_)%2]}
$r

Try it online!

mazzy

Posted 2014-02-16T00:31:40.303

Reputation: 4 832

0

><>,  34  33 bytes

|!/?=0:,2-}:%2:+***"  @"(0:
n{\~{

Try it online!

Emigna

Posted 2014-02-16T00:31:40.303

Reputation: 50 798

0

Smalltalk (Smalltalk/X), 63/78

the first version creates an intermediate string (78):

t:=Number readFrom:Stdin.
((15to:1by:-1)collect:[:i|$0+(t>>i&1)]as:String)print

actually, there is no need to create the string; just output the chars (63):

t:=Number readFrom:Stdin.
15to:1by:-1 do:[:i|($0+(t>>i&1))print]

mhmh - is there a shorter way to read to a number?

blabla999

Posted 2014-02-16T00:31:40.303

Reputation: 1 869

0

Python 3.x: 65 characters

b=lambda n:n<2 and'01'[n]or b(n//2)+b(n%2);print(b(int(input())))

dan04

Posted 2014-02-16T00:31:40.303

Reputation: 6 319

0

C# - 104

string p(int d){var r="";long i=1;while(r.Length<=64){var g=d&i;r=(g!=0)? "1"+r:"0"+r;i=i<<1;}return r;}

This method will convert decimal to binary up to 64 bits.

When executed the above method in Linqpad - rr = p(-32768); rr.Dump();

Output: 01111111111111111111111111111111111111111111111111000000000000000

Rajesh

Posted 2014-02-16T00:31:40.303

Reputation: 11

The spec calls for "an input string". It looks like this method accepts an int. – Poke – 2016-06-16T20:19:00.303

0

Bash, 44

f=b+=n/2**e%2*10**e,2**e++/n?f=b:f;echo $[f]

Pass an input value to the script through the environment variable n. The decimal representation of the binary result cannot exceed LONG_MAX.

This should also be compatible with ksh93 and zsh if b and e are initialized to 0 and proper arithmetic expansion is used.

ormaaj

Posted 2014-02-16T00:31:40.303

Reputation: 153

1

I don't believe this is valid since it assumes that n is already defined, making it a snippet. That could be fixed by taking input as a command-line argument and setting n to that in your script.

– a spaghetto – 2015-12-22T20:14:49.443

@quartata Variables in a math context in shell are implicitly zero. For the purpose of golf it makes more sense to do n=127 sh -c '...' than sh -c 'n=$1 ...' _ 127. There's no reason to prefer one over the other in this case as they're both perfectly typical way to pass values. – ormaaj – 2015-12-22T22:14:31.847