Преобразовать дробь в повторяющиеся десятичные


17

Почти полярная противоположность, если это вызов, и я подозреваю, что это будет немного легче.

Ваша задача - взять два целых числа в формате a/b(формирование рационального числа), а затем вывести число точно в десятичном виде.

Например, если бы вы вводили 1/3, он бы вывел:

0.33333333333333333

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

Поведение для x/0будет неопределенным. Для числа, которое выглядит так, как будто оно не повторяется (например, скажем 5/4), оно действительно повторяется. Любая из следующих двух форм будет приемлемой для 5/4:

1.25000000000000000
1.24999999999999999

(То же самое с целыми числами 1.9999999или 2.000000)

Фракция не может быть в своей простейшей форме, aили bможет быть отрицательным (Примечание -a/b = -(a/b), -a/-b = a/b, a/-b = -a/bи -.6249999является недействительным, но -0.6249999приемлемо, но вы все еще можете использовать.


Можем ли мы использовать Unix bcили это обман?
Дэвид Р. Триббл

Прежде чем я продолжу играть в гольф, мой ответ: может aи / или bбыть отрицательным?
Деннис

@ Денис Да, но либо aили b(или оба) могут быть отрицательными)

@DavidRTribble Я думаю, что это стандартная лазейка, так что нет.

Ваше последнее редактирование говорит, что ведущие нули в порядке с положительными числами, но не отрицательными? Если так, то в чем причина?
Geobits

Ответы:


2

CJam, 38 37 байт

l'/%:i2*~*0<'-*o:Dmd\zo'.{oA*Dmd\z1}g

Как это устроено

l     e# Read line from STDIN.            STACK '17/-13'
'/%   e# Split at '/'.                    STACK ['17' '-13']
:i    e# Cast each element to int.        STACK [17 -13]
2*~   e# Duplicate and dump the array.    STACK 17 -13 17 -13
*     e# Multiply.                        STACK 17 -13 -221
0<    e# Compare with zero.               STACK 17 -13 1
'-*o  e# Print '-' that many times.       STACK 17 -13
:D    e# Save the topmost integer in D.   STACK 17 -13
md    e# Perform modular division.        STACK -1 4
\z    e# Swap and take absolute value.    STACK 4 1
o'.   e# Print and push '.'.              STACK 4 '.'
{     e# do:
  o   e#   Print.                         STACK 4
  A*  e#   Multiply by 10.                STACK 40
  Dmd e#   Divide modulo D.               STACK -3 1
  \z  e#   Swap and take absolute value.  STACK 1 3
  o   e#   Print.                         STACK 1
1}g   e# while(1)

Так как вы используете двойное деление, не слишком ли это плохо для больших чисел?
Орлп

@orlp: полностью. Это исправлено сейчас.
Деннис

6

С 108 79

Изменить, чтобы работать с отрицательными числами.

Ввод от стандартного ввода. Старый стиль K & R.

main(a,b){char*s="-%d.";scanf("%d/%d",&a,&b);for(a*b<0?(a<0?a=-a:(b=-b)):++s;printf(s,a/b);s="%d")a=a%b*10;}

4

Рубин, 83 69 102 91 89 байт

->s{a,b=s.scan(/\d+/).map &:to_i
eval(s+?r)<0&&$><<?-
$><<a/b<<?.
loop{a=a%b*10
$><<a/b}}

Простая реализация ручного целочисленного деления на основе целочисленного деления компьютера.

Спасибо @blutorange за помощь в игре в гольф.

Изменить: Исправлено решение, чтобы включить отрицательные числа.


2
Используя некоторые ярлыки в ruby, вы можете уменьшить это до 66 байт: ->s{a,b=s.split(?/).map &:to_i;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}мне просто нравится это в ruby.
Blutorange

Вау, я только что многому научился, спасибо! Я не помнил, ?/чтобы обозначать символы, и я не знал, $><<чтобы напечатать или loopключевое слово. Большое спасибо!!
rorlork

1
Пожалуйста, я не знал о многих из этих уловок, пока кто-то не указал на это. $>это сокращение от $stdout, и <<является оператором. Вы можете сохранить еще один байт во второй строке, изменив его на c*d<0&&$><<?-; несколько байтов путем объединения 3-й / 4-й строки до $><<a/b<<?.и еще одного путем удаления пробела после <<последней строки. И вот идея уменьшить его до 91 байта: ->s{a,b=s.scan(/\d+/).map &:to_i;1==s.count(?-)&&$><<?-;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}(ruby 2.2.0)
blutorange

Синтаксис для $><<a/bне работал правильно, поэтому я поместил там пробел. Остальное кажется хорошим, большое спасибо!
rorlork

1
Если вам все еще интересно, существует также рациональный литерал ( Rational(2,3) == 2/3r) начиная с ruby ​​2.1 (который я узнал около 10 минут назад), который можно использовать для сокращения второй строки:eval(s+?r)<0&&$><<?-
blutorange

2

Ява, 177 176 170

s->{try{int x=new Integer(s.split("/")[0]),y=new Integer(s.split("/")[1]),z=1;for(;;x=x%y*10,Thread.sleep(999))System.out.print(x/y+(z-->0?".":""));}catch(Exception e){}}

Алгоритм прост; сложная часть заставляла печать работать. В конце концов, компьютер перестал спать на секунду между каждым шагом, чтобы он мог печатать.

Расширенная, работоспособная версия

public class RepeatedDecimal {
    public static void main(String[] args) {
        java.util.function.Consumer<String> f = s -> {
                try {
                    int x = new Integer(s.split("/")[0]),
                        y = new Integer(s.split("/")[1]),
                        z = 1;
                    for (;; x = x % y * 10, Thread.sleep(999)) {
                        System.out.print(x / y + (z-- > 0 ? "." : ""));
                    }
                } catch (Exception e) { }
                };

        f.accept("5/7");
    }
}

В то время как выход имеет проблему сброса, я смог заставить его отображать вывод, спя в течение 9 мс, что побрило бы два байта.

@ Снеговик Это, вероятно, зависит от оборудования или ОС; мой компьютер не будет работать с менее чем 250 мс или около того.
Ypnypn

2

R 103 137 109 103

Немного счастливее с этим сейчас. Сканирование с разделителем позволяет сэкономить много байтов. Возможно, еще есть место для улучшения. Заменено <-на =. Не всегда было удача с этим, но на этот раз это сработало.

cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)

Тестовые прогоны

> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -1/3
3: 
Read 2 items
-0.33333333333333333333...
> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -5/-4
3: 
Read 2 items
1.250000000000000000000...

1

Python 3, 107 115 байт

a,b=map(int,input().split("/"))
print(("%.1f"%(a/b))[:-1],end="")
b=abs(b)
while 1:a=abs(a)%b*10;print(a//b,end="")

Довольно просто:

  • Введите числитель и знаменатель
  • Выведите частное с 1 цифрой после десятичной точки, затем снимите последнюю цифру (например, -1/3-> -0.)
  • Принять абсолютные значения *
  • Loop:
    • Числитель является остатком после деления знаменателя
    • Умножить числитель на 10
    • Выведите целое число как следующую цифру

* (Хотя расчет aбыл перемещен внутри цикла, чтобы сохранить несколько байтов.)

Редактировать: Исправлена ​​ошибка с отрицательными дробями> -1.


0

Python 2,7, 209 байт

from sys import*;m,o=1,lambda x:stdout.write(str(x));a,b=[int(x)for x in argv[1].split('/')]
o(str(a*b)[0]);a,b=abs(a),abs(b);o('0'*(b>a))
while 1:
 while not((m*a)/b):o('0.'[m==1]);m*=10
 o((m*a)/b);a=(m*a)%b

редактировать:

Теперь выводит все символы в одной строке, как и просили.

edit2:

Теперь читает дробь из аргумента командной строки, как требуется :)


1
Несколько советов: 1) Использование mapвместо понимания списка экономит совсем немного; 2) не нужны круглые скобки m*aв любом из своих мест, так как *, %и /все же приоритет и левоассоциативные; 3) логику 0 или точка в строке 3 можно упростить "0."[m==1], поскольку вы все равно просто ее печатаете; 4) вероятно, сохранит символы, чтобы просто установить o=stdout.writeи преобразовать числовые аргументы в строку с обратными галочками по мере необходимости.
DLosc

1
Кроме того, код не работает с негативами: 1/-3дает -1.666666666вместо -0.333333333.
DLosc
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.