实基转换


19

对于基数转换,我们遇到了一些挑战,但是所有这些挑战似乎都适用于整数值。用实数做吧!

挑战

输入:

  • 以10为底的实数正数 x。可以将其视为双精度浮点数或字符串。为了避免精度问题,可以将该数字假定为大于10 -6且小于10 15
  • 目标基站 b。这是2到36之间的整数。
  • 数的小数位的 Ñ。这是1到20之间的整数。

输出:xn的底数b中表示形式,带有n个小数位。

在计算输出表达式时,第n个以外的数字应被截断(而不是四舍五入)。例如,x = 3.141592653589793在base中b = 310.0102110122...,因此n = 3输出将是10.010(截断),而不是10.011(舍入)。

对于在小数部分中产生有限位数的xb,还允许使用等效的无限表示形式(截断为n位)。例如,4.5十进制也可以表示为4.49999...

不用担心浮点错误

输入输出格式

x将不带前导零。如果x恰好是整数,则可以假定它的小数部分为零(3.0),也可以不为小数部分(3)。

输出是灵活的。例如,可以是:

  • 代表数字的字符串,在整数和小数部分之间带有合适的分隔符(小数点)。位1112等等(对于b超过10)可以表示为字母AB像往常一样,或任何其它不同的字符(请注明)。
  • 一个字符串用于整数部分,另一个字符串用于小数部分。
  • 两个数组/列表,每个部分一个,包含从035数字的数字。

唯一的限制是整数和小数部分可以分开(合适的分隔符)并使用相同的格式(例如,[5, 11]对于表示整数部分['5', 'B']的列表和对于表示分数部分的列表,否)。

附加规则

测试用例

输出被示出为与数字串0,..., 9A,..., Z,使用.作为小数点分隔符。

x, b, n                    ->  output(s)

4.5, 10, 5                 ->  4.50000 or 4.49999
42, 13, 1                  ->  33.0 or 32.C
3.141592653589793, 3, 8    ->  10.01021101
3.141592653589793, 5, 10   ->  3.0323221430
1.234, 16, 12              ->  1.3BE76C8B4395
10.5, 2, 8                 ->  1010.10000000 or 1010.01111111
10.5, 3, 8                 ->  101.11111111
6.5817645, 20, 10          ->  6.BCE2680000 or 6.BCE267JJJJ
0.367879441171442, 25, 10  ->  0.94N2MGH7G8
12944892982609, 29, 9      ->  PPCGROCKS.000000000


因为42, 13, 1我们可以33代替33.0吗?
LiefdeWen

@LiefdeWen不,挑战的必要部分是输出必须具有n十进制数字
Luis Mendo

Answers:



7

JavaScript(ES8),81 74 71字节

f=
(x,b,n,g=x=>x.toString(b))=>g(x-x%1)+'.'+g(x%1).substr(2,n).padEnd(n,0)
<div oninput=o.textContent=f(+x.value,b.value,n.value)><input id=x><input type=number min=2 max=36 value=10 id=b><input type=number min=1 max=20 value=10 id=n><pre id=o>

在浮点错误蔓延之前,根据和适合x1e-6和之间1e21b236(完全按要求),n1到任何东西1048取决于基数。编辑:在@Birjolaxew的帮助下,保存了7个字节。在@tsh的帮助下又保存了3个字节。先前的74字节版本还可以使用负数:

f=
(x,b,n,[i,d]=`${x.toString(b)}.`.split`.`)=>i+`.`+d.slice(0,n).padEnd(n,0)
<div oninput=o.textContent=f(+x.value,b.value,n.value)><input id=x><input type=number min=2 max=36 value=10 id=b><input type=number min=1 max=20 value=10 id=n><pre id=o>


1
如何用正则表达式进行基本转换?!
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer我不是,这只是一个高尔夫球手(希望)n从字符串中提取“数字”的方式。
尼尔

那么什么你的函数的核心逻辑是什么?
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer为什么,当然是JavaScript的内置基本转换功能。(提示:看看我在哪里使用基本参数。)
Neil

哦,它说.toString(b)......我哑> _ <
埃里克Outgolfer

5

Python 2中153个 149 144 137 135 109字节

def f(x,b,m):
 i=int(x);s=[];t=[]
 while i:s=[i%b]+s;i/=b
 while m:m-=1;x=x%1*b;t+=[int(x)]
 return s or[0],t

没注意到我可以将数字作为数字返回,这样就更简单了。返回两个数字列表,第一个数字列表为整数部分,第二个数字为小数部分。

在线尝试!


在情况下,它可以帮助:我已经加了注释,你只需要大于支持号码1e-6(和小于1e15,如前)
路易斯Mendo

5

Perl 6,25个字节

->\x,\b,\n{+x .base(b,n)}

尝试一下

展开:

-> \x, \b, \n {
  +x            # make sure it is a Numeric
  .base( b, n ) # do the base conversion
}

请注意,空格是这样的,因此它(+x).base(b,n)
不会被解析+( x.base(b,n) )


在情况下,它可以帮助:我已经加了注释,你只需要大于支持号码1e-6(和小于1e15,如前)
路易斯Mendo

3

Mathematica,158个字节

由于@KellyLowder已在mathematica中很好地回答了这一难题,因此我尝试(用不同的方法)得出测试用例中所示的准确结果

ToUpperCase[""<>Insert[StringReplace[ToString@BaseForm[#,p]&/@PadRight[#&@@(d=RealDigits[#,p=#2]),w=(#3+d[[2]])][[;;w]],"\n "<>ToString@p->""],".",d[[2]]+1]]&


输入

[12944892982609,29,9]

输出

PPCGROCKS.000000000


3

红宝石,45字节

->x,b,n{(x*b**n).round.to_s(b).insert(~n,?.)}

为什么?

由于基数b中的b ^ n为10 ^ n,我们将x乘以该数字,然后将其所属的小数点相加。

在线尝试!


-1字节+错误修正,替换.round.to_i;这会将输出的最后一位固定为与测试输出不匹配的位。使用-1多一个字节.insert ~n,?.,不带括号。
Nnnes

3

C(gcc)157 152字节

需要64位long int才能与较大的测试用例一起使用。

-5字节归功于Peter Cordes

#define P r=99;i=l=x;do{z[--r]=48+7*(l%b>9)+l%b;}while(l/=b);printf(z+r)
long i,r,l;char z[99];f(x,b,n)double x;{P;putchar(46);while(n--){x=(x-i)*b;P;}}

在线尝试!

编辑:如果允许输出由换行符分隔的两个字符串,则可以剃掉几个字节:

149个字节:

#define P r=99;i=l=x;do{z[--r]=48+7*(l%b>9)+l%b;}while(l/=b);printf(z+r)
long i,r,l;char z[99];f(x,b,n)double x;{P;puts("");while(n--){x=(x-i)*b;P;}}

编辑:这不是最长的提交,是的!


2
printf(z+r)如果不包含任何%字符,则可以使用。(这是代码高尔夫;安全性和良好实践不在窗口内:P)。您还可以puts(z+r)免费获取换行符(puts("")在第二版中保存)。
彼得·科德斯

谢谢!我忘了直接提供char *作为模式,这确实节省了很多字节:-)在第二个版本中,我不能使用puts(z + r),因为那将意味着每个小数点将被打印在换行符上
scottinet

啊,如果没有带注释的非高尔夫版本,那么最后一部分是不明显的。
彼得·科德斯

float比短double,但似乎该问题确实需要double输入或字符串。
彼得·科德斯

1
没必要。C的一些常见实现确实具有64位long,并且根据代码高尔夫球规则,所有使您的答案有效的必要条件。(此外,C和C ++代码高尔夫球的答案通常都假定为64位long,因为这是“在线试用”所使用的。)我建议回滚您的编辑,并仅添加一个注释,例如“ long必须为64位以支持更大的测试用例。”
彼得·科德斯

2

Mathematica 47字节

TakeDrop@@r[#,#2,#3+Last@(r=RealDigits)[#,#2]]&

调用RealDigits两次以首先找出小数点左边的位数。


在情况下,它可以帮助:我已经加了注释,你只需要大于支持号码1e-6(和小于1e15,如前)
路易斯Mendo

1
我以为问题只是在问TakeDrop@@RealDigits[##]&,但后来我意识到我读错了东西-您的解决方案似乎是最佳的。
Mark S.


1

188字节的Haskell

f=fromIntegral
g 0 _=[]
g n p=g(div n p)p++[mod n p]
z=(!!)(['0'..'9']++['A'..'Z']++['.'])
h x p l|(i,d)<-properFraction x=z<$>(g i p++[36]++(last$g(floor$d*(f p**f l))p:[0<$[1..l]|d==0]))

在线尝试!

g 将数字转换为以给定基数表示该数字的列表

z将整数映射到字母(36 = .

h 将先前的函数应用于数字的整数和小数部分。


1

公理,566字节

c:=alphanumeric()::List Character
f(a:INT,b:PI):List Character==(r:=[];repeat(y:=a rem b;r:=cons(c.(y+1),r);a:=a quo b;a=0=>break);r)
g(x)==floor(x)::INT
F(x)==>for i in 1..#x repeat z:=concat(z,x.i)
w(a:Float,b:PI,n:NNI):String==
  z:="";b<2 or b>36 or a<0=>z
  ip:=g(a);    fp:=g((a-ip)*b^n)
  ipb:=f(ip,b);fpb:=f(fp,b);cnt:=n-#fpb
  for i in 1..cnt repeat fpb:=cons(c.1,fpb)
  F(ipb);z:=concat(z,".");F(fpb)
  z

h(a,b,n)==>(n>=0 and b>0=>(nd123:=10+g(n*log_2(b)/log_2(10));mxv123456:=digits(nd123::PI);res78484:=w(a,b,n);digits(mxv123456);res78484);"")

这个问题特别困难;再写一些时间后,似乎可以使用一个宏来保存digits()来产生正确的结果。

(7) -> h(4.5,10,5)
   (7)  "4.50000"
                                                             Type: String
(8) -> h(42,13,1)
   (8)  "33.0"
                                                             Type: String
(9) -> h(%pi,3,8)
   (9)  "10.01021101"
                                                             Type: String
(10) -> h(%pi,5,10)
   (10)  "3.0323221430"
                                                             Type: String
(11) -> h(1.234,16,12)
   (11)  "1.3BE76C8B4395"
                                                             Type: String
(12) -> h(0.367879441171442,25,10)
   (12)  "0.94N2MGH7G8"
                                                             Type: String
(13) -> h(12944892982609,29,9)
   (13)  "PPCGROCKS.000000000"
                                                             Type: String
(14) -> h(6.5817645,20,10)
   (14)  "6.BCE267JJJJ"
                                                             Type: String

真正的目标是一个转换为基数2..36的函数,每个浮点数[具有k:= digits()]或每个计算得出的数字为%pi或%e或两个浮点数/整数的除法如1./3 。['oo'数字]

(15) -> h(%pi,13,800)
   (15)
  "3.1AC1049052A2C77369C0BB89CC9883278298358B370160306133CA5ACBA57614B65B410020
  C22B4C71457A955A5155B04A6CB6CC2C494843A8BBBBA9A039B77B34CB0C036CAC761129B3168
  B8BAB860134C419787C911812985646C7AAA3025BAA118B3AB8265CB347852065667291482145
  6C533447BC53A5262177C9985455C395626091A2CC3126B395C91B65B654A1804226197528410
  29A8A4A55CC7937B347B77B5A914127B11C6A57A84510775A9A467819A468B6B74339CC1290B2
  24921C6A771BC2AB6AB41735119C2231545A86399483119AAA5AC34B46B7B5C9089946A364860
  9B26CB0BAC0ABCBA182C12881933AA93C3942C71AA664753989A3C82166BA2109796C4A134607
  59725A72C9117AC980556A147557C319438287226C94725B125753B009387A48AA45CB1960A04
  A064052C00A6069371949872B14590895C555CB01A39B7589824B8621618A8B1971841201A2AB
  B04B80C7534CC1CB079581491995B46C679555316288C82665645A1A600C1A669B865651B6B842470C018B03C1115B3C4306C015C0B45C"
                                                             Type: String

1

公理,127字节

g(a)==floor(a)::INT;f(a:Float,b:PI,n:NNI):Any==(b<2 or n>28=>%i;x:=g(a);radix(x,b)+radix(g((a-x)*b^n),b)::RadixExpansion b/b^n)

结果

(4) -> f(%e,2,10)
   (4)  10.1011011111
                                                   Type: RadixExpansion 2
(5) -> f(%e,3,10)
   (5)  2.2011011212
                                                   Type: RadixExpansion 3
(6) -> f(%e,35,10)
   (6)  2.P4VBNEB51S
                                                  Type: RadixExpansion 35
(7) -> f(1.4,35,10)
   (7)  1.DYYYYYYYYY
                                                  Type: RadixExpansion 35
(8) -> f(%pi,3,8)
   (8)  10.01021101
                                                   Type: RadixExpansion 3
(9) -> f(%pi,5,10)
   (9)  3.032322143
                                                   Type: RadixExpansion 5
(10) -> f(1.234,16,12)
   (10)  1.3BE76C8B4395
                                                  Type: RadixExpansion 16

最后的零示例有一点问题

 f(4.5,10,5)

将返回“ 4.5”而不是“ 4.50000”

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.