Реальная базовая конверсия

19

У нас было несколько проблем с базовым преобразованием, но все они, похоже, применимы к целочисленным значениям. Давайте сделаем это с реальными числами!

Соревнование

Входы:

  • Действительное положительное число x , выраженное в базе 10. Это может быть принято как число с плавающей запятой двойной точности или как строка. Чтобы избежать проблем с точностью, можно предположить, что число больше 10 -6 и меньше 10 15 .
  • Целевые базовые б . Это будет целое число от 2 до 36.
  • Количество дробных цифр п . Это будет целое число от 1 до 20.

Выход: представление о х в базовой Ь с п дробных цифр.

При вычислении выходного выражения цифры за пределами n-й должны быть усечены (не округлены). Например, x = 3.141592653589793в базе b = 3есть 10.0102110122..., поэтому для n = 3вывода будет 10.010(усечение), а не 10.011(округление).

Для x и b, которые дают конечное число цифр в дробной части, также допускается эквивалентное бесконечное представление (усеченное до n цифр). Например, 4.5в десятичном виде также можно представить как 4.49999....

Не беспокойтесь об ошибках с плавающей запятой .

Формат ввода и вывода

х будет дан без начальных нулей. Если x окажется целым числом, вы можете предположить, что оно будет дано с нулевой десятичной частью ( 3.0) или без десятичной части ( 3).

Выход гибкий. Например, это может быть:

  • Строка, представляющая число с подходящим разделителем (десятичная точка) между целыми и дробными частями. Цифры 11и 12т. Д. (Для b больше 10) могут быть представлены в виде букв A, Bкак обычно, или в виде любых других отдельных символов (просьба указать).
  • Строка для целочисленной части и другая строка для дробной части.
  • Два массива / списка, по одному для каждой части, содержащие числа от 0до 35как цифры.

Единственными ограничениями являются то, что целые и дробные части могут быть разделены (подходящий разделитель) и использовать один и тот же формат (например, нет [5, 11]для списка, представляющего целую часть, и ['5', 'B']для списка, представляющего дробную часть).

Дополнительные правила

Контрольные примеры

Вывод показан в виде строки с цифрами 0, ..., 9, A..., 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
Луис Мендо
источник
Давайте продолжим эту дискуссию в чате .
Эрик Outgolfer
ибо 42, 13, 1мы можем иметь 33вместо 33.0?
LiefdeWen
@LiefdeWen Нет, важной частью задачи является то, что выходные данные должны иметь nдесятичные цифры
Луис Мендо

Ответы:

1

Желе , 16 байт

*×⁵b⁸ḞðṖḣ⁹,ṫø⁹N‘

Попробуйте онлайн!

Обратите внимание, что синглтоны печатаются как элемент на выходе.

Дрянная Монахиня
источник
Эй, что случилось с твоей фотографией?
Луис Мендо
@LuisMendo некоторые люди не могут сделать это, так как он был подключен к Facebook
Leaky Nun
Вы знаете, что можете загрузить картинку здесь, верно? Те по умолчанию так безличны
Луис Мендо
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>

Работает xмежду 1e-6и 1e21, bот 2до 36(точно так же, как требуется) иn от 1до чего угодно от 10до в 48зависимости от базы до появления ошибок с плавающей запятой. Редактирование: 7 байт с помощью @Birjolaxew. Сохранено еще 3 байта с помощью @tsh. Предыдущая 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
Как сделать базовое преобразование с помощью регулярных выражений?!?
Эрик Outgolfer
@EriktheOutgolfer Я не являюсь, это всего лишь способ игры в гольф (надеюсь) для извлечения до n"цифр" из строки.
Нил
Тогда что является основной логикой вашей функции?
Эрик Outgolfer
@EriktheOutgolfer Почему, конечно, встроенная базовая функция преобразования JavaScript. (Подсказка: посмотрите, где я использую базовый параметр.)
Нил
О, это говорит .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

Не заметил, что я могу просто вернуть цифры в виде чисел, так что это намного проще. Возвращает два списка цифр, первый для целой части, второй для дробной части.

Попробуйте онлайн!

Arfie
источник
На случай, если это поможет: я добавил примечание, что вам нужно поддерживать только числа больше 1e-6(и меньше, чем 1e15раньше)
Луис Мендо
5

Perl 6 , 25 байт

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

Попытайся

Expanded:

-> \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) ).

Брэд Гилберт b2gills
источник
На случай, если это поможет: я добавил примечание, что вам нужно поддерживать только числа больше 1e-6(и меньше чем 1e15, как и раньше)
Луис Мендо
3

Mathematica, 158 байт

Поскольку этот вопрос уже получил очень хороший ответ в Mathematica от @KellyLowder, я попытался (с другим подходом) получить точные результаты, как показано в тестовых примерах.

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

J42161217
источник
3

Рубин , 45 байт

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

Почему?

Поскольку b ^ n в базе b равно 10 ^ n, мы умножаем x на это число, а затем добавляем десятичную точку, к которой оно принадлежит.

Попробуйте онлайн!

гигабайт
источник
-1 байт + исправление путем замены .roundна .to_i; это исправляет последнюю цифру вывода для тех, где она не совпадает с результатами теста. -1 байт больше .insert ~n,?.без использования круглых скобок.
17
3

C (gcc) ,157 152 байта

long intДля работы с большими контрольными примерами требуется 64 бита .

-5 байт благодаря Питеру Кордесу

#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;}}

редактировать: это представление не самое длинное, ууу!

scottinet
источник
2
Вы можете использовать, printf(z+r)если он не содержит %символов. (Это код-гольф; безопасность и хорошие практики выходят в окно: P). Вы также можете использовать, puts(z+r)чтобы получить новую строку бесплатно (сохранение puts("")во второй версии).
Питер Кордес
Благодарность! Я забыл о предоставлении char * непосредственно в качестве шаблона, это действительно экономит немало байтов :-) Я не могу использовать put (z + r) во второй версии, так как это будет означать, что каждое десятичное число будет напечатано на новой
строке
Ах, эта последняя часть не была очевидна без разглаженной версии с комментариями.
Питер Кордес
floatкороче double, но, похоже, вопрос требует doubleввода или строки.
Питер Кордес
1
Нет необходимости в этом. Некоторые распространенные реализации C имеют 64-битную версию long, и согласно правилам code-golf это все, что вам нужно, чтобы ваш ответ был действительным. (Кроме того, ответы на вопросы о коде-гольфе на C и C ++ обычно принимают 64-битные long, поскольку именно это использует Try It Online.) Я бы предложил откатить ваши правки, и просто добавить примечание типа " longдолжно быть 64-битным для это для поддержки больших тестовых случаев. "
Питер Кордес
2

Mathematica 47 байт

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

Вызов RealDigitsдважды, чтобы сначала выяснить количество цифр слева от десятичной дроби.

Келли Лоудер
источник
На случай, если это поможет: я добавил примечание, что вам нужно поддерживать только числа больше 1e-6(и меньше, чем 1e15прежде)
Луис Мендо
1
Я думал, что вопрос просто спрашивает, TakeDrop@@RealDigits[##]но потом я понял, что неправильно понял - ваше решение кажется оптимальным.
Марк С.
2

SageMath , 68 байт

def f(n,b,k):y=n.str(b).split('.')+[''];return y[0],(y[1]+'0'*k)[:k]

Попробуйте онлайн!

Уриэль
источник
На случай, если это поможет: я добавил примечание, что вам нужно поддерживать только числа больше 1e-6(и меньше чем 1e15, как и раньше)
Луис Мендо
1

Haskell , 188 байт

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 применяет предыдущие функции к целой и дробной части числа.

jferard
источник
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);"")

это был особенно сложный вопрос; после некоторого времени в записи чего-то, правильные результаты, которые, кажется, генерируются с использованием одного макроса для сохранения цифр () ... это не слишком много для игры в гольф ... результаты:

(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 или деления двух чисел с плавающей точкой / int, как в 1./3 , ['оо' цифры]

(15) -> h(%pi,13,800)
   (15)
  "3.1AC1049052A2C77369C0BB89CC9883278298358B370160306133CA5ACBA57614B65B410020
  C22B4C71457A955A5155B04A6CB6CC2C494843A8BBBBA9A039B77B34CB0C036CAC761129B3168
  B8BAB860134C419787C911812985646C7AAA3025BAA118B3AB8265CB347852065667291482145
  6C533447BC53A5262177C9985455C395626091A2CC3126B395C91B65B654A1804226197528410
  29A8A4A55CC7937B347B77B5A914127B11C6A57A84510775A9A467819A468B6B74339CC1290B2
  24921C6A771BC2AB6AB41735119C2231545A86399483119AAA5AC34B46B7B5C9089946A364860
  9B26CB0BAC0ABCBA182C12881933AA93C3942C71AA664753989A3C82166BA2109796C4A134607
  59725A72C9117AC980556A147557C319438287226C94725B125753B009387A48AA45CB1960A04
  A064052C00A6069371949872B14590895C555CB01A39B7589824B8621618A8B1971841201A2AB
  B04B80C7534CC1CB079581491995B46C679555316288C82665645A1A600C1A669B865651B6B842470C018B03C1115B3C4306C015C0B45C"
                                                             Type: String
RosLuP
источник
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»

RosLuP
источник