二进制到十进制转换器


32

二进制到十进制转换器

据我所知,我们没有一个简单的二进制到十进制转换的挑战。


编写一个程序或函数,该程序或函数采用正的二进制整数并输出其十进制值。

不允许使用任何内置的基本转换函数。整数到小数的函数(例如,101010变成[1, 0, 1, 0, 1, 0]或的函数"101010")不受此规则约束,因此被允许。

规则:

  • 该代码必须支持二进制数,最高为您的语言支持的最大数值(默认情况下)
  • 您可以选择在二进制表示形式中包含前导零
  • 十进制输出可能没有前导零。
  • 输入和输出格式是可选的,但数字之间不能有任何分隔符。(1,0,1,0,1,0,1,0)不是有效的输入格式,但两者10101010(["10101010"])都是。
    • 您必须沿“正常”方向输入。111014不是7

测试用例:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

该挑战与其他一些挑战相关,例如thisthisthis



输出必须是未签名的还是可以签名的?另外,如果我的语言碰巧会根据值的长度在32位和64位整数之间自动切换,那么可以在两个范围内对输出进行签名吗?例如,有两个二进制值将转换为十进制-132 1's64 1's
milk

另外,输出是否可以浮动,是否需要为整数?
Carcigenicate's

@Carcigenicate它必须是整数,但可以是任何数据类型。只要round(x)==x您还好:) 2.000就可以接受输出10
Stewie Griffin

哦太好了。谢谢。
Carcigenicate's

Answers:


56

果冻,5个字节

DḤ+¥/

在线尝试!

说明

enter image description here

演员表

  • D是monad(单参数函数):数字,1234变成[1, 2, 3, 4]

  • 是一个单引号加倍的单子。

  • + 是一个dyad(两个参数的函数),它添加了左右参数。

从那里开始,它变得有些棘手。

这是解析时发生的情况

  • D+阅读。链条看起来像[D, Ḥ, +]

  • 接下来的两个字符是quicks,其作用类似于到目前为止我们已经阅读的链接(函数)上的解析时后缀运算符。

  • ¥被读取时,最后两个环节得到弹出,并通过其作用类似于通过组合它们形成的对子的链接取代。因此,现在链看起来像[D, dyad(Ḥ+)]

  • /被读取时,最后一个环节(这应该是一个对子)被弹出,并且由一个单子取代折叠使用这种对子(直观地:f/取一个列表,以替换逗号它f,并评估结果。)

  • 最后的链看起来像是[D, fold(dyad(Ḥ+))]两个单子。

这是运行时发生的情况

  • 输入(一个数字)被隐式读入工作值(例如101010)。

  • D被执行,用数字([1,0,1,0,1,0])代替工作值。

  • fold(dyad(Ḥ+))被执行时,代替与所述工作值1∗0∗1∗0∗1∗0,其中是对子Ḥ+

那么,x∗y评估结果如何呢?

  • 在二元定义中,工作值最初是参数x

  • ,即double monad ,会使此值翻倍。现在的工作价值是2x

  • +加号 dyad缺少正确的论点,因此这是一个钩子:一种特殊的句法模式,此dyad的正确论点被注入+。得出2x + y最终的工作值,并将其返回。

因此,整个表达式的计算结果为:

1∗0∗1∗0∗1∗0 = 2×(2×(2×(2×(2×1+0)+1)+0)+1)+0
            = 32×1 + 16×0 + 8×1 + 4×0 + 2×1 + 1×0
            = 42

10
您的解释越来越好:-)
路易斯·门多

2
嘿,我猜您从现在开始要这么做吗?太棒了,+ 1。
暴民埃里克(Erik the Outgolfer)

4
我认为这是我所了解的第一份果冻。+1!
蓝色

太棒了 我实际上了解我最初认为只是看似随机字符的混乱情况。精彩的解释。
猪鱼

1
@Mark Jelly有其自己的代码页,以使程序看起来更美,更易读,但程序也可以只是字节串。
林恩

20

Python 2,49 37 31 30字节

现在,它将以十进制表示形式取一个二进制数,因为Python可以处理任意大的整数。

b=lambda n:n and n%2+2*b(n/10)

感谢xnor节省了一个字节:)

观察其工作原理的最简单方法是查看将二进制转换为十进制的基本公式:

= 101010 
= 1*(2^5) + 0*(2^4) + 1*(2^3) + 0*(2^2) + 1*(2^1) + 0*(2^0)
= 1*32 + 0*16 + 1*8 + 0*4 + 1*2 + 0*1
= 42

这是一种“标准”的转换方式。您可以像这样展开第三行:

= ((((1*2 + 0)*2 + 1)*2 + 0)*2 + 1)*2 + 0

这基本上就是我所做的递归方法所要做的。

我有替代解决方案:

b=lambda n:n and n%10+2*b(n/10)
b=lambda n:n%10+2*(n and b(n/10))
b=lambda n:0if n<1else n%10+2*b(n/10)
b=lambda n:0**(n/10)or n%10+2*b(n/10)
b=lambda n,o=0:o*(n<'0')or b(n[1:],2*o+int(n[0]))
lambda j:sum(int(b)*2**a for a,b in enumerate(j,1))

6
您可以执行n%5n%2代替n%10
xnor

@xnor啊,不确定我是怎么错过的!谢谢:)
卡德

12

05AB1E,6个字节

码:

$¦v·y+

对于外植,让我们以101010为例。我们从数字1(由第一个数字表示)开始。在那之后,我们有两种情况:

  • 如果数字为0,则将数字乘以2。
  • 如果数字是1,则将数字乘以2并加1。

因此,对于101010情况,计算如下:

  • 1 01010,以数字1开头。
  • 1 0 1010乘以2,得到2
  • 10 1 010,乘以2并加1,得到5
  • 101 0 10乘以2,得出10
  • 1010 1 0,乘以2并加1,得到21
  • 10101 0乘以2,得到42,这是期望的结果。

代码说明:

$         # Push 1 and input
 ¦        # Remove the first character
  v       # For each character (starting with the first)
   ·      #   Multiply the carry number by two
    y+    #   Add the current character (converted automatically to a number)

使用CP-1252编码。在线尝试!


好东西!(虽然我只是注意到,但不适用于0)
Emigna '16

@Emigna是的,幸运的是,您的代码只需要对正二进制数起作用。
阿德南

甚至都没看到。然后非常好:)
Emigna '16

9

Haskell中,16 111 + 57 = 168个字节

import Data.String
instance IsString[Int]where fromString=map((-48+).fromEnum)
f::[Int]->Int
f=foldl1((+).(2*))

+57个字节用于编译标志-XOverloadedStrings-XOverlappingInstances-XFlexibleInstances

挑战具有一些麻烦的IO格式,因为它很大程度上取决于源代码中数据类型的表达方式。我的第一个版本(16个字节),即

foldl1((+).(2*))

接受一个整数列表,例如[1,0,1,0,1,0],并被声明为无效,因为文字Haskell列表恰好,在元素之间。本身不禁止列出。在我的新版本中,我使用了非常相同的函数(现在名为)f,但是我重载了“用引号括起来的字符序列”。正如在类型注释中所见,该函数仍然采用整数列表[Int] -> Int,但是现在可以将具有一位整数的列表写为"1234",例如

f "101010"

计算结果为42。不幸的Haskell,因为本机列表格式不符合挑战规则。顺便说一句,f [1,0,1,0,1,0]仍然有效。


2
不幸的是,列表不是有效的输入。
乔纳森·艾伦

@JonathanAllan:为什么?如果是这样,它应该怎么接受输入呢?在Haskell中,字符串只是字符列表。
nimi 2016年

我不知道为什么...但我询问这个早早就和编辑了添加“ (1,0,1,0,1,0,1,0)不是一个有效的输入格式,但两者10101010(["10101010"])有。” 此外,有注释建议,如果这是解释字符串输入的方式,则可接受字符数组。
乔纳森·艾伦

1
@JonathanAllan:任何“二进制整数”(我们必须接受的输入)本质上都是分隔的,它是2的幂的序列。限制是关于显式分隔符(在数字之间),而不是分隔。我必须以某种方式将数字分开。
nimi 2016年

2
这里OP:如果有可能的输入10101010"10101010"或者类似的东西,并使其工作,然后提交有效。您可以将其称为字符串,列表,整数等。输入[1][0][1][0][1,0,1,0]不正确。基本上,应该可以在某处连续击中一堆一和零。这清楚吗?
Stewie Griffin

7

视网膜,15字节

从二进制转换为一元,然后从一元转换为十进制。

1
01
+`10
011
1

在线尝试


不允许使用任何内置的基本转换函数。〜OP
罗马格拉夫

10
@RomanGräf没有。我只是在描述解决方案的过程。
mbomb007 '16

7

PHP,44字节

for(;""<$c=$argv[1][$i++];)$n+=$n+$c;echo$n;

我可能发誓说我以前见过这个问题。很好

从左到右读取数字,向左移动并添加当前位。


7

JavaScript(ES6),33 31字节

s=>[...s].map(c=>r+=+c+r,r=0)|r

编辑:较短但不太甜:由于@ETHproductions,节省了2个字节。


通常情况下,.map时间更短:s=>[...s].map(c=>+c+r+r,r=0)|r
ETH生产

@ETHproductions函数如何返回除0以外的任何值?
尼尔

抱歉,应该是s=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions 2016年

7

迷宫17 15字节

-+:
8 +
4_,`)/!

在线尝试!

Image of the code

迷宫是一种基于堆栈的二维语言。在迷宫中,代码执行就像迷宫一样,遵循代码的路径,其中的迷宫以空格作为墙壁,并从最左上角的非空格字符开始。代码流由堆栈顶部的符号确定。由于堆栈的底部具有隐式零,因此前四个指令(-+:+)不起作用。

循环从开始 ,

  • , 将下一个输入字符的ascii代码值压入堆栈的末尾;如果EOF,则压入-1。
  • _48 将48推入栈顶
  • -弹出y,弹出x,按x-y。前面的指令的作用是从输入中减去48,得出“ 0”为0,为“ 1”为1。
  • +弹出y,弹出x,按x+y
  • : 复制堆栈顶部
  • + 该指令和上一条指令的作用是将当前值乘以2

因此,代码的循环部分实际上是将当前数字乘以2并根据输入的字符是1还是0加上1或0。

尾巴

如果堆栈的顶部为负(表示找到了EOF),则代码将在交界处左转(朝分号)。

  • 否定堆栈顶部以获得1
  • ) 递增堆栈顶部以获得2
  • /弹出y,弹出x,按x / y(整数除法)。这样可以取消*2循环中的最后一个。
  • !输出堆栈顶部的整数表示。在这一点上,程序由于陷入死胡同而转弯,然后由于试图除以零而出错并退出。

感谢@Martin Ender为我节省了2个字节(并教我如何在迷宫中更好地思考)。


代替_48-您可以简单地做,#%但是不幸的是,我看不到它如何对字节计数有所帮助。
马丁·恩德

可以使用`)而不是保存一个字节;_2
马丁·恩德

@MartinEnder,我不理解您对的评论#%。您能解释一下如何_48-将其从ascii转换为int 吗?感谢您的)提示。我将进行更改。
罗伯特·希克曼

那时程序中总是有两个值,因此#是的缩写_2。虽然_2%不是将ASCII转换为整数的通用转换方法,但它在这里可以使用,因为您只对前两位数字感兴趣。一个替代方案是_1&(因为模2只是提取最低有效位)。
马丁·恩德

哦。那太好了。但是,是的,我不确定如何使用该替换(#%)来缩短整体代码。
罗伯特·希克曼

6

脑高射炮46,28个字节

([]){{}({}<>({}){})<>([])}<>

在线尝试!

多亏@Riley,节省了很多字节!

由于脑筋急转弯不能接受二进制输入,因此输入是“ 0”和“ 1”的列表。

说明:

#Push the height of the stack
([])

#While true:
{

 #Pop the height of the stack
 {}

 #Push this top number to (the other stack * 2)
 ({}<>({}){})

 #Toggle back on to the main stack
 <>

 #Push the new height of the stack
 ([])

#endwhile
}

#Toggle back to the other stack, implicitly display.
<>

喜欢解释!没有它,很难阅读:)
Emigna '16

2
^。如果我不给自己留下任何评论,我什至无法阅读自己的程序。
莱利2016年

您可以通过删除整个if部分将其减少到32个字节,对于“将数字添加到其他堆栈”步骤,只需将其添加到(其他堆栈)* 2中即可。([]){({}[()]<({}<>({}){})><>)}<>
莱利

您可以通过在开始时弹出并在末尾再次按下高度来保存另外4个。([]){{}({}<>({}){})<>([])}<>
莱利2016年

@Riley哦,天哪,那是天才。非常感谢你!
DJMcMayhem

6

Java,84 79 46 48字节

  • 版本3.1

更改为long/ 48个字节:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • 3.0版

打高尔夫球/ 46字节:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • 版本2.0

感谢@Geobits!/ 79个字节:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • 版本1.0

84个字节:

s->{for(int i=-1,j=0;++i<s.length;)if(s[i]>48)j+=Math.pow(2,s.length-i+1);return j;}

1
猜猜我应该做一个迭代的解决方案。卢尔兹 干得好

输入类型是List <Character>还是String?如果是后者,我不知道Java8可以做到!如果是前者,挑战是否允许?

s应该是char[]。我希望允许...
RomanGräf16年

这里的返回类型是什么?我认为应该比较长,因为每个OP都必须“代码必须支持二进制数,直到您的语言支持的最大数值”,但对于较小的值,我认为它会返回一个int值
Poke

1
也许还不错,每输入类型。可能希望将2字节命中作为输出imo

4

Befunge-98,12个字节

2j@.~2%\2*+

在线尝试!

一次从输入读取一个char,通过取其值模2(0为char(48),1为char(49))将其转换为0或1,然后使用将当前值加倍并加每次都有新数字。

奖励: 这适用于任何类型的输入字符串,我已经尝试了一段时间,以找到任何有趣的输入->输出组合,但是我什么也没能产生(可悲的是,“ answer” = 46)。你是否可以?


大声笑。我在用答案玩同一游戏。我能产生的最有趣的数字是666
詹姆斯·霍尔德尼斯

好东西!我没有找到适合666的东西:D如果资本化对价值产生影响,这会容易
Leo

@James Holderness-我一直在做同样的事情,但我只发现了“ le年”能带回366,你的确很棒。
蓝绿色鹈鹕

4

Javascript(ES7)41 40 36字节

f=([c,...b])=>c?c*2**b.length+f(b):0

以字符串作为输入

由于ETHproductions节省了一个字节

f=([c,...b])=>c?c*2**b.length+f(b):0
document.write([
    f('101010'),
    f('11010'),
    f('10111111110'),
    f('1011110010110'),
].join("<br>"))


1
从右到左的关联性**很奇怪,但是在这里使用它很不错。1<<b.length会做同样的事情,但是它要求括号不能被解析为(c*1)<<(b.length+...)。我认为您可以通过替换b[0]为来节省一个字节b+b请参阅此处)。
ETHproductions 2016年

4

C#6,85 37 36字节

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • 多亏了Kade节省了41个字节!
  • 更改为C#6可以节省另外7个字节。

也许可以提供一些启发?;)
Kade

@Kade确实如此,谢谢!我一直在寻找它采用相同的技术,在您链接的同一时刻Python的答案:DI可以得到甚至用C#6.短
Yytsi


3

C,53

v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}

与我的JavaScript答案相同

测试Idone


您可以通过声明vc作为全局变量来保存4个字节(尽管您需要更改的名称v,因为它已经是函数的名称),如下所示:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox 2016年

@Steadybox可能是,w,c;但我不想在答案是一个函数时使用全局变量(即使在代码高尔夫中)
edc65

@Steadybox Globals也默认为0,因此您可以删除=0
algmyr '16

3

Perl,25个字节

-3个字节,感谢@Dom Hastings。

24个字节的代码+ 1个字节的-p标志

$\|=$&<<$v++while s/.$//

要运行它:

perl -pe '$\|=$&<<$v++while s/.$//' <<< 101010

说明:

$\|=$&<<$v++  # Note that: we use $\ to store the result
              # at first $v=0, and each time it's incremented by one
              # $& contains the current bit (matched with the regex, see bellow)
              # So this operation sets a $v-th bit of $\ to the value of the $v-th bit of the input
while         # keep doing this while...
s/.$//        #  ... there is a character at the end of the string, which we remove.
         # $\ is implicitly printed thanks to -p flag

3

Pushy, 10 bytes

Takes input as a list of 0/1 on the command line: $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

The algorithm really shows the beauty of having a second stack:

            \ Implicit: Input on stack
L:    ;     \ len(input) times do:
  v         \   Push last number to auxiliary stack
   K2*      \   Double all items
       OS#  \ Output sum of auxiliary stack

This method works because the stack will be doubled stack length - n times before reaching number n, which is then dumped into the second stack for later. Here's what the process looks like for input 101010:

1: [1,0,1,0,1,0]
2: []

1: [2,0,2,0,2]
2: [0]

1: [4,0,4,0]
2: [2]

1: [8,0,8]
2: [2,0]

1: [16,0]
2: [2,0,8]

1: [32]
2: [2,0,8,0]

1: []
2: [2,0,8,0,32]

2 + 8 + 32 -> 42

3

Matlab, 30 Bytes

@(x)sum(2.^find(flip(x)-48)/2)

The last test case has rounding errors (because of double), so if you need full precision:

@(x)sum(2.^uint64(find(flip(x)-48))/2,'native')

with 47 Bytes.


I can't test this, but I believe @(x)sum(2.^(find(flip(x)-48)-1)) will give the correct result for all cases for 32 bytes. flip works like fliplr if x is one dimensional.
Stewie Griffin

Nice solution! I also ran into the rounding error, thanks for the fix. What is the format of x? Calling flip or fliplr on a number just returns that number.
MattWH

x is the binary string, so call it with f=@(x)..; f('1111001010').
Jonas

3

Retina, 12 bytes

Byte count assumes ISO 8859-1 encoding.

+%`\B
¶$`:
1

Try it online!

Alternative solution:

+1`\B
:$`:
1

Explanation

This will probably be easier to explain based on my old, less golfed, version and then showing how I shortened it. I used to convert binary to decimal like this:

^
,
+`,(.)
$`$1,
1

The only sensible way to construct a decimal number in Retina is by counting things (because Retina has a couple of features that let it print a decimal number representing an amount). So really the only possible approach is to convert the binary to unary, and then to count the number of unary digits. The last line does the counting, so the first four convert binary to unary.

How do we do that? In general, to convert from a list of bits to an integer, we initialise the result to 0 and then go through the bits from most to least significant, double the value we already have and add the current bit. E.g. if the binary number is 1011, we'd really compute:

(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
           ^        ^        ^        ^

Where I've marked the individual bits for clarity.

The trick to doing this in unary is a) that doubling simply means repeating the number and b) since we're counting the 1s at the end, we don't even need to distinguish between 0s and 1s in the process. This will become clearer in a second.

What the program does is that it first adds a comma to the beginning as marker for how much of the input we've already processed:

^
,

Left of the marker, we'll have the value we're accumulating (which is correctly initialised to the unary representation of zero), and right of the value will be the next bit to process. Now we apply the following substitution in a loop:

,(.)
$`$1,

Just looking at ,(.) and $1,, this moves the marker one bit to the right each time. But we also insert $`, which is everything in front of the marker, i.e. the current value, which we're doubling. Here are the individual steps when processing input 1011, where I've marked the result of inserting $` above each line (it's empty for the first step):

,1011

1,011
 _
110,11
   ___
1101101,1
       _______
110110111011011,

You'll see that we've retained and doubled the zero along with everything else, but since we're disregarding them at the end, it doesn't matter how often we've doubled them, as long as the number of 1s is correct. If you count them, there are 11 of them, just what we need.

So that leaves the question of how to golf this down to 12 bytes. The most expensive part of the 18-byte version is having to use the marker. The goal is to get rid of that. We really want to double the prefix of every bit, so a first idea might be this:

.
$`$&

The problem is that these substitutions happen simultaneously, so first bit doesn't get doubled for each bit, but it just gets copied once each time. For input 1011 we'd get (marking the inserted $`):

 _ __ ___
1101011011

We do still need to process the input recursively so that the doubled first prefix is doubled again by the second and so on. One idea is to insert markers everywhere and repeatedly replace them with the prefix:

\B
,
+%`,
¶$`

首次用前缀替换每个标记后,我们需要记住输入的开始位置,因此我们也要插入换行符并使用 % option to make sure that the next $` only picks up things up the closest linefeed.

确实可以,但是它仍然太长(1末尾计数s时为16个字节)。我们如何扭转局面?通过匹配来标识我们要插入标记的位置,而不是在该位置插入非数字字符。这会将非单词边界变为单词边界,这相当于更早删除标记字符。这就是12字节解决方案的作用:\B (a position between two digits). Why don't we simply insert prefixes into those positions? This almost works, but the difference is that in the previous solution, we actually removed one marker in each substitution, and that's important to make the process terminate. However, the \B aren't character but just positions, so nothing gets removed. We can however stop the \B

+%`\B
¶$`:

仅出于完整性考虑,以下是处理的各个步骤,1011每个步骤后均带有一个空行:

1
1:0
10:1
101:1

1
1:0
1
1:0:1
1
1:0
10:1:1

1
1:0
1
1:0:1
1
1:0
1
1:0:1:1

同样,您会发现最后一个结果恰好包含11 1s。

As an exercise for the reader, can you see how this generalises quite easily to other bases (for a few additional bytes per increment in the base)?


2

T-SQL, 202 Bytes

DECLARE @b varchar(max)='1',@ int=1 declare @l int=LEN(@b)declare @o bigint=CAST(SUBSTRING(@b,@l,1)AS bigint)WHILE @<@l BEGIN SET @o=@o+POWER(CAST(SUBSTRING(@b,@l-@,1)*2AS bigint),@)SET @=@+1 END PRINT @o

2

PHP, 64 bytes

foreach(str_split(strrev($argv[1]))as$k=>$v)$t+=$v*2**$k;echo$t;

We reverse our binary number, split it into its component digits, and sum them based on position.


2

Bash + GNU utilities, 29 bytes

sed 's/./2*&+/g;s/.*/K&p/'|dc

I/O via stdin/stdout.

The sed expression splits the binary up into each digit and builds a RPN expression for dc to evaluate.


2

PowerShell v2+, 55 bytes

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i

Feels too long ... Can't seem to golf it down any -- tips appreciated.

Explanation

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i
param($n)$j=1;                                          # Take input $n as string, set $j=1
              $n[$n.length..0]                          # Reverses, also converts to char-array
                              |%{                  };   # Loop over that array
                                 $i+=+"$_"*$j;          # Increment by current value of $j times current digit
                                              $j*=2     # Increase $j for next loop iteration
                                                     $i # Leave $i on pipeline
                                                        # Implicit output

2

JavaScript (ES6), 32 bytes

f=([...n])=>n+n&&+n.pop()+2*f(n)

Recursion saves the day again! Though the parameterization seems a little long...


Since it's a single "argument", does [...n] need to be surrounded in parentheses?
Cyoce

@Cyoce Unfortunately, yes, or JS throws a SyntaxError.
ETHproductions

2

Mathematica, 27 13 11 bytes

Fold[#+##&]

Accepts a List of bits as input (e.g. {1, 0, 1, 1, 0} -- Mathematica's binary representation of the number 22)


Following up from the comment on Greg's answer, how is "splitting all the digits in the input" not a base conversion function?
Martin Ender

@MartinEnder I'm using it like the Characters function.
JungHwan Min

@MartinEnder Actually, as seen in @nimi's answer, I could just accept a list of 1s and 0s because that is the only way to represent a binary number in Mathematica, meaning I don't need IntegerDigits in the first place.
JungHwan Min

That assumes that base 10 is the "natural" representation of an integer. An actual integer value has no preferred base attached to it (I guess you could say the way it's stored is probably base 256 or maybe even base 2 but that's an implementation detail). Just because we (normally) use base 10 to write integer literals there doesn't mean integer values are already in base 10.
Martin Ender

@MartinEnder @Lynn's Jelly code uses D, which does the same thing as IntegerDigits
JungHwan Min

2

Clojure, 114 105 63 41 bytes

V4: 41 bytes

-22 bytes thanks to @cliffroot. Since digit is a character, it can be converted to it's code via int, then have 48 subtracted from it to get the actual number. The map was also factored out. I don't know why it seemed necessary.

#(reduce(fn[a d](+(* a 2)(-(int d)48)))%)

V3: 63 bytes

(fn[s](reduce #(+(* %1 2)%2)(map #(Integer/parseInt(str %))s)))

-42 bytes (!) by peeking at other answers. My "zipping" was evidently very naïve. Instead of raising 2 to the current place's power, then multiplying it by the current digit and adding the result to the accumulator, it just multiplies the accumulator by 2, adds on the current digit, then adds it to the accumulator. Also converted the reducing function to a macro to shave off a bit.

Thanks to @nimi, and @Adnan!

Ungolfed:

(defn to-dec [binary-str]
  (reduce (fn [acc digit]
            (+ (* acc 2) digit))
          (map #(Integer/parseInt (str %)) binary-str)))

V2: 105 bytes

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range)(reverse %)))

-9 bytes by reversing the string so I don't need to create an awkward descending range.

V1: 114 bytes

Well, I'm certainly not winning! In my defense, this is the first program I've ever written that converts between bases, so I had to learn how to do it. It also doesn't help that Math/pow returns a double that requires converting from, and Integer/parseInt doesn't accept a character, so the digit needs to be wrapped prior to passing.

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range(dec(count %))-1 -1)%))

Zips the string with a descending index representing the place number. Reduces over the resulting list.

Ungolfed:

(defn to-dec [binary-str]
  (reduce (fn [acc [place digit]]
            (let [parsed-digit (Integer/parseInt (str digit))
                  place-value (long (Math/pow 2 place))]
              (+ acc (* parsed-digit place-value))))
          0
          (map vector (range (dec (count binary-str)) -1 -1) binary-str)))

#(reduce(fn[a b](+(* a 2)(-(int b)48)))0 %) improved version. Moved map part of code directly into reduce, changed integer parsing method, make external function with shorthand lambda syntax.
cliffroot

@cliffroot int can be used to parse!? That'll knock off like 10 bytes in every challenge I've done here lol.
Carcigenicate

Oh, I see what you're doing. Taking the ascii code, then subtracting to get the value. I guess this would only work in select circumstances only. Oh well, thanks for the tip.
Carcigenicate

2

Perl, 21 19 16 + 4 = 20 bytes

-4 bytes thanks to @Dada

Run with -F -p (including the extra space after the F). Pipe values to the function using echo -n

$\+=$_+$\for@F}{

Run as echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

I feel this is sufficiently different from @Dada's answer that it merits its own entry.

Explanation:

-F                              #Splits the input character by character into the @F array
-p                              #Wraps the entire program in while(<>){ ... print} turning it into
while(<>){$\+=$_+$\for@F}{print}
                   for@F        #Loops through the @F array in order ($_ as alias), and...
          $\+=$_+$\             #...doubles $\, and then adds $_ to it (0 or 1)...
while(<>){              }       #...as long as there is input.
                         {print}#Prints the contents of $_ (empty outside of its scope), followed by the output record separator $\

This uses my personal algorithm of choice for binary-to-decimal conversion. Given a binary number, start your accumulator at 0, and go through its bits one by one. Double the accumulator each bit, then add the bit itself to your accumulator, and you end up with the decimal value. It works because each bit ends up being doubled the appropriate number of times for its position based on how many more bits are left in the original binary number.


Even shorter : perl -F -pE '$\+=$_+$\for@F}{'
Dada

I honestly laughed at how short this is now. Thank you.
Gabriel Benamy

Yea, it's pretty neat, well done!
Dada

2

R (32-bit), 64 Bytes

Input for the function should be given as character. The base functions of R support 32-bit integers.

Input:

# 32-bit version (base)
f=function(x)sum(as.double(el(strsplit(x,"")))*2^(nchar(x):1-1))
f("1")
f("10")
f("101010")
f("1101111111010101100101110111001110001000110100110011100000111")

Output:

> f("1")
[1] 1
> f("10")
[1] 2
> f("101010")
[1] 42
> f("1101111111010101100101110111001110001000110100110011100000111")
[1] 2.016121e+18

R (64-bit), 74 Bytes

Input for the function should be given as character. The package bit64 has to be used for 64-bit integers.

Input:

# 64-bit version (bit64)
g=function(x)sum(bit64::as.integer64(el(strsplit(x,"")))*2^(nchar(x):1-1))
g("1")
g("10")
g("101010")
g("1101111111010101100101110111001110001000110100110011100000111")

Output:

> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567

2
You can do: el(strsplit(x,"")) instead of strsplit(x,split="")[[1]] to save a couple of bytes.
Billywob

Thanks a lot! Especially for the el function - I was not aware of it.
djhurio

2

Dyalog APL, 12 bytes

(++⊢)/⌽⍎¨⍞

get string input

⍎¨ convert each character to number

reverse

(...)/ insert the following function between the numbers

++⊢ the sum of the arguments plus the right argument


ngn shaved 2 bytes.


1

k, 8 bytes

Same method as the Haskell answer above.

{y+2*x}/

Example:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.