Реализовать произвольное деление точности

15

Реализуйте функцию, divide(int a, int b, int c)которая печатает базовое значение 10 a/b. без использования математических и BigInteger/ BigDecimalили эквивалентных библиотек с плавающей запятой вообще. Должны быть напечатаны как минимум cточные символы в наборе 0123456789., за исключением (возможного) исключения в пункте 4 ниже.

  1. aи bможет быть любыми 32-битными целыми числами. Обновление: если для целей игры в гольф вы хотите, чтобы входные данные были 64-битными примитивами, это нормально, но вам не нужно поддерживать весь 64-битный диапазон данных.
  2. Вам не нужно проверять, что cявляется положительным (хотя, надеюсь, ваша программа не падает), если это не так.
  3. Минимальная поддерживаемая верхняя граница для cIS 500. Это нормально, если ваша программа не поддерживает значения cвыше 500, но это также нормально, если это так.
  4. Для чисел, которые делятся поровну, вы можете выбрать, печатать ли дополнительные нули (в зависимости от значения c) или ничего.
  5. Вам не нужно иметь возможность использовать эту функцию для выполнения каких-либо дальнейших задач с частным, единственная цель - печать.
  6. Для чисел между -1и 1, это ваш выбор, печатать ли ведущий 0. Однако это единственный сценарий, в котором допустима печать начального нуля, и вы можете напечатать только один такой ноль.
  7. Вы можете использовать любую логику округления / пола / потолка, которую вы предпочитаете для последнего десятичного знака.
  8. Для отрицательного ответа вы должны напечатать ведущий -. Это не считается в сторону c. Тем не менее, это ваш выбор , если вы хотите, чтобы напечатать , +или ничего для положительного ответа.
  9. Целочисленное деление и целочисленный модуль разрешены. Однако имейте в виду, что вы ограничены примитивами, если только вы не решите реализовать свою собственную BigInteger/ BigDecimalбиблиотеку, которая учитывает длину вашего кода.
  10. Вам не нужно обращаться с bсуществом 0, хотя вы можете, если хотите. Ваша программа может войти в бесконечный цикл или аварийно b=0завершить работу , если вы не будете оштрафованы.
  11. Небольшое изменение правила за комментарий. Для того, чтобы убедиться , что игровое поле является уровень, в то время как aи bгарантированно 32 - битные целые числа, вы можете использовать 64 битные длинные целые числа. Если выбранный вами язык выходит за пределы 64-битных целых чисел в качестве примитива, вы ни в коем случае не можете использовать эту функциональность (притворяться, что он ограничен 64-битными).
  12. Еще один момент, который неясен (однако он не должен изменять ни один из текущих действительных ответов): хотя cего можно интерпретировать как число напечатанных символов или количество пробелов после десятичной дроби, ваша программа должна cкаким-то образом использовать соответствующим образом решить, сколько символов печатать. Другими словами, divide(2,3,2)должен быть намного короче, чем divide(2,3,500); не нормально печатать 500 символов без учета c.
  13. На самом деле меня не волнует название функции. dэто нормально для целей игры в гольф.

вход

И вызов функции и чтение из stdinпринимаются. Если вы читаете из stdin, любой символ, не входящий в набор [-0123456789], считается разделителем аргументов.

Выход

Персонажи stdoutкак описано выше.

пример

для divide(2,3,5), все следующие являются приемлемыми результатами:

0.666
0.667
.6666
.6667
 0.666
 0.667
 .6666
 .6667
+0.666
+0.667
+.6666
+.6667

Другой пример: для divide(371,3,5)следующего все приемлемые результаты:

123.6
123.7
 123.6
 123.7
+123.6
+123.7
123.66666
123.66667
 123.66666
 123.66667
+123.66666
+123.66667

И для divide(371,-3,5)следующего все приемлемо:

-123.6
-123.7
-123.66666
-123.66667
durron597
источник
Для ровного игрового поля может быть целесообразно указать конкретную максимальную длину в битах, которую можно использовать (примитив или иным образом), если вы не сверните свою собственную более крупную реализацию, поскольку а) в некоторых языках длина битов примитивов варьируется в зависимости от основная архитектура и б) в некоторых языках типы больших чисел являются примитивами.
Джонатан Ван Матр
@JonathanVanMatre Добавлено правило 11 за ваш комментарий
durron597
1
Как вы считаете точные цифры ? В вашем примере я вижу три или четыре, но никогда не пять, как указывает последний аргумент.
Говард
@ Говард, если бы ты сделал 92,3,5ответ, например,30.67
durron597
1
кстати 370/3 = 123,333 лол
изабера

Ответы:

5

Ява, 92/128

void d(long a,int b,int c){if(a<0^b<0){a=-a;p('-');}for(p(a/b+".");c>0;c--)p((a=a%b*10)/b);}<T>void p(T x){System.out.print(x);}

Я должен был импровизировать так, чтобы aили bмогло быть -2147483648, поскольку положительные 32-разрядные целые числа учитываются только в 2147483647, поэтому он aстал long. Может быть лучший способ обработки отрицательных результатов, но я не знаю ни одного ( doubles, вероятно, заставили бы это работать так, abs(a) < abs(b)как они имеют, -0но только одно дополнение сохранило бы точность).

Почему двухбайтовые числа? Мне понадобилось 92 байта для вычисления и 36 для помощника по печати ( System.out.printотстой; в общем, Java - это не игра в гольф).

public class Div {

    void d(long a, int b, int c) {
        if (a < 0 ^ b < 0) {
            a = -a;
            p('-');
        }
        for (p(a / b + "."); c > 0; c--) {
            p((a = a % b * 10) / b);
        }
    }

    <T> void p(T x) {
        System.out.print(x);
    }

    public static void main(String[] args) {
        final Div div = new Div();
        div.d(12345, 234, 20);
        div.p('\n');
        div.d(-12345, 234, 20);
        div.p('\n');
        div.d(234, 234, 20);
        div.p('\n');
        div.d(-234, 234, 20);
        div.p('\n');
        div.d(234, 12345, 20);
        div.p('\n');
        div.d(234, -12345, 20);
        div.p('\n');
        div.d(-234, 12345, 20);
        div.p('\n');
        div.d(-234, -12345, 20);
        div.p('\n');
        div.d(-2147483648, 2147483647, 20);
        div.p('\n');
        div.d(2147483647, -2147483648, 20);
        div.p('\n');
    }
}

Метод в основном использует то, чему большинство из нас научилось в школе, чтобы получить запрошенные десятичные цифры.

TheConstructor
источник
Официальное постановление: я бы сказал, что игнорировать Integer.MIN_VALUEнехорошо, но в longкачестве вклада это нормально.
durron597
Это намного короче. Красиво сделано.
durron597
@ durron597 спасибо. Все еще строгая типизация и System.outзаставляет Java чувствовать себя громоздким ;-) Все еще хорошее чувство, что уже есть более длинные ответы, отправленные.
TheConstructor
1
@ durron597 Вы специально попросили функцию, поэтому я подумал, что это не считается. Если бы мне пришлось использовать импорт, чем, вероятно, да.
TheConstructor
1
По крайней мере, нет $ для каждой переменной ;-)
TheConstructor
9

С 98 95 89

d(a,b,c){if(a>0^b>0)a=-a,printf("-");for(printf("%d.",a/b);c--;putchar(a/b+48))a=a%b*10;}

печатает cцифры после.

пример вывода:

d(2,3,5);
0.66666

d(-2,3,5);
-0.66666

d(24352345,31412,500);
775.25611231376543995925124156373360499172290844263338851394371577740990704189481726728638736788488475741754743410161721635043932255189099707118298739335285878008404431427479943970457150133706863618999108620909206672609193938622182605373742518782630841716541449127721889723672481854068508850120972876607665860180822615560932127849229593785814338469374761237743537501591748376416656055010823888959633261174073602444925506175983700496625493441996689163377053355405577486310963962816757926906914554947153953

d(-77,12346463,500);
-0.00000623660395693892250760399962321192717298873369644407471192356871761572524859953818352673150196943043525906974329409159530142357369879940514137530724386409289850866600418273638369142644334656816288195250736992448768525852302801215214430238036593962173620088603513411087855687900251270343579371679160258286118056645048869461642577311412993340683886551152342172814999729072204727783171585254821563066280601982932277851559592411203111368818745903178910429650985873444078680671541315111866451144752954

должно работать для -2147483647 <= a <= 2147483647, то же самое для b. обработка -была болью.

онлайн версия: ideone

izabera
источник
Это работает для существа -2147483648? Не знаю, c компиляторы достаточно хорошо, чтобы сказать, какой целочисленный тип назначен вашим параметрам.
TheConstructor
спасибо за указание на это. он работает правильно для -2147483647 <= a <= 2147483647, то же самое для b. есть проблема, когда a = -2147483648 и b положительно из-за a=-a.
Изабера
Я пытался, но в итоге получил то же решение, что и вы. Вы можете сохранить один символ, поняв, что printf("-")возвращает 1.
Томас
4

PHP, 108

function d($a,$b,$c){$a*$b<0&&$a*=-print'-';for($p='.';$c--;$a.=0,print$i.$p,$p='')$a-=$b*$i=($a-$a%$b)/$b;}

Он работает, просто выводя частное a/ bво время цикла cшагов, aполучая остаток, умноженный на 10 на каждой итерации.

DEMO

Разван
источник
Дает странные результаты, когда a или b отрицательны
TheConstructor
Я исправил ошибку для отрицательных чисел. Благодарность!
Разван
Только что нашел 112 версию вашего кода: function d($a,$b,$c){if($a*$b<0)$a*=-print'-';for($p='.';$c--;$a*=10,$p=''){$a-=$b*$i=($a-$a%$b)/$b;echo$i.$p;}}смотрите возвращаемое значение
TheConstructor
Благодарю. Я даже обновил вашу версию и сумел выиграть лишний 1 байт.
Разван
2

Python 111

f=lambda a,b,c:'-'[a*b>=0:]+'%s'%reduce(lambda(d,r),c:(d%c*10,r+`d/c`+'.'[r!='':],),[abs(b)]*c,(abs(a),''))[-1]

Это решение не нарушает ни одно из заявленных правил.

Abhijit
источник
2

C: 72 символа

d(a,b,c){for(printf("%d.",a/b);c--;putchar((a=abs(a)%b*10)/abs(b)+48));}

Он почти полностью делает то, что должен делать. Тем не менее, как и некоторые другие ответы здесь, он даст неправильные значения или потерпит неудачу, d(-2147483648,b,c)и d(a,-2147483648,c)поскольку абсолютное значение -2147483648 выходит за пределы для 32-разрядного слова.

Форс
источник
2

Perl, без арифметики, 274 байта

Это евклидово длинное деление, которое может потреблять необычное количество памяти. Самое близкое к математике для чисел с плавающей запятой это использование битовых операций для их анализа.

sub di{($v,$i,$d,$e)=(0,@_);($s,$c,$j)=$i=~s/-//g;$s^=$d=~s/-//g;
$i=~s/\.(\d+)/$j=$1,""/e;$d=~s/\.(\d+)/$c=$1,""/e;
$z=0.x+length($c|$j);$i.=$j|$z;$d.=$c|$z;
($e,$m,$z,$t)=(1.x$e,0.x$i,0.x$d,"-"x($s&1));
for(;$e;$t.="."x!$v,$v=chop$e){$t.=$m=~s/$z//g||0;$m="$m"x10}
print"$t\n"}

Примеры:

di(-355,113,238);
di(1.13,355,239);
di(27942,19175,239);
di(1,-90.09,238);
di("--10.0","----9.801",239);
di(".01",".200",239);

Выход:

-3.141592920353982300884955752212389380530973451327433628318
584070796460176991150442477876106194690265486725663716814159
292035398230088495575221238938053097345132743362831858407079
646017699115044247787610619469026548672566371681415929203539

0.0031830985915492957746478873239436619718309859154929577464
788732394366197183098591549295774647887323943661971830985915
492957746478873239436619718309859154929577464788732394366197
183098591549295774647887323943661971830985915492957746478873

1.4572099087353324641460234680573663624511082138200782268578
878748370273794002607561929595827900912646675358539765319426
336375488917861799217731421121251629726205997392438070404172
099087353324641460234680573663624511082138200782268578878748

-0.011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011

1.0203040506070809101112131415161718192021222324252627282930
313233343536373839404142434445464748495051525354555657585960
616263646566676869707172737475767778798081828384858687888990
919293949596979900010203040506070809101112131415161718192021

0.0500000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
user130144
источник
1

Руби, 178

def d(a,b,c)
    n=(a<0)^(b<0)
    a=-a if n
    m=a/b-b/a
    l=m.to_s.size-1
    g=(a*10**(10+c)/b).to_s
    f=m<0?"."+"0"*(l-1)+g[0..c-l-1] : g[0..l]+"."+g[l+1..c-2]
    p n ? "-"+f : f
end

Онлайн версия для тестирования.

Хитрость заключается в том, чтобы умножить a на довольно большое число, поэтому в результате получается просто целое число, кратное операции с плавающей запятой. Затем точка и нули должны быть вставлены в нужном месте в результирующей строке.

Дэвид Херрманн
источник
Это работает для с больше чем 350?
durron597
Я проверил это с c = 1000 - код дал мне ответ, может быть, я должен проверить реальный результат, хотя ...
Дэвид Херрманн
2
действительно gвыйти за пределы 64 бит для больших c? Изменить: я думаю, что вы неявно используете BigIntegerздесь
durron597
Err, gэто строка, но перед вызовом to_sвы создали в памяти номер, размер которого превышает 64 бита
durron597
1
Это понятно - и делает задачу более сложной (и интересной)! Лучше удалить ответ или оставить его другим, чтобы иметь пример того, как не выполнить задачу?
Дэвид Херрманн
1

Python 92 байта:

def d(a,b,c):c-=len(str(a/b))+1;e=10**c;a*=e;a/=b;a=str(a);x=len(a)-c;return a[:x]+'.'+a[x:]

Я думаю, что возможно еще немного игры в гольф .....

Maltysen
источник
2
действительно eвыйти за пределы 64 бит для больших с? Изменить: я думаю, что вы неявно используете BigIntegerздесь.
durron597
1
@ durron597 я очень сомневаюсь в этом. Это идет к BigInt (Long в python), но 2 ** 45 это 48 бит. Достаточно ли этого? Кроме того, python не имеет примитивов, так что ...
Maltysen
Если a=5и c=400после e=10**c, в шестнадцатеричном формате номер будет длиной 333 цифры. Начинается 8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...это более 64 бит.
durron597
@ durron597 400 ... мне это нужно
Maltysen
1
Да, правило 3 гласит, что вам нужно поддерживать как минимум до 500 ... Я пытался предотвратить это (имитационное) решение.
durron597
1

С 83

d(a,b,c){printf("%d.",a/b);for(a=abs(a),b=abs(b);c--&&(a=a%b*10);)putchar(a/b+48);}

Та же идея, которую я использовал в своей реализации Python

Abhijit
источник
Очень хорошо! Тем не менее, он падает наd(-2147483648,-1,10)
durron597