实现任意精度划分


15

实现一个函数divide(int a, int b, int c),以输出以10为底的值a/b。而不使用任何浮点数学或BigInteger/ BigDecimal或等效库。除下面第4点中的(可能的)例外外,至少必须打印c一组正确的字符0123456789.

  1. ab可以是任何的32个整数。更新:如果打高尔夫球的目的,你想有输入是64个原语是好的,但你并不需要支持数据的全部64位范围。
  2. 如果不是,则无需检查是否c为正(尽管希望您的程序不会崩溃)。
  3. 的最小支持上限c500。如果您的程序不支持c上述值可以500,但是也可以。
  4. 对于均分的数字,是选择打印额外的零(基于的值c)还是不打印任何内容。
  5. 您不需要使用该函数就可以执行任何其他任务,唯一的目标是打印。
  6. 对于之间的数字-11,这是你的选择是否打印的领先0。但是,这是唯一可以接受打印前导零的情况,并且您只能打印一个这样的零。
  7. 您可以使用最后一个小数位所需的舍入/下限/ ceil逻辑。
  8. 对于否定答案,您必须打印前导-。这不计入c。然而,这是你的选择,如果你想打印+或者没有一个肯定的回答。
  9. 整数除法和整数模数均允许。但是,请记住,除非您选择实现自己的BigInteger/ BigDecimal库(取决于代码长度),否则您仅限于基元。
  10. 尽管您可以,但是您不需要处理bbeing 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

为了公平竞争起见,最好给出一个可以使用的特定最大位长(原始的或其他方式),除非您滚动自己的较大实现,因为a)在某些语言中,原语的位长取决于基础架构和b)在某些语言中,大数字类型基元。
乔纳森·范·马特雷

@JonathanVanMatre在您的评论中添加了规则11
durron597 2014年

1
您如何计算准确的数字?在您的示例中,我看到的是最后一个参数所显示的3或4,但从没有5。
2014年

@霍华德,如果您92,3,5回答了,例如,30.67
durron597

1
btw 370/3 = 123.333哈哈
izabera 2014年

Answers:


5

Java,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);}

我必须即兴创作,以便ab可能是-2147483648,因为正的32位整数仅计入2147483647,这就是为什么a成为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');
    }
}

该方法基本上是行使我们大多数人在学校学到的东西来生成所需的十进制数字。


官方裁定:我想说忽略Integer.MIN_VALUE是不行的,但是long作为投入是可以的。
durron597

这要短得多。做得很好。
durron597 2014年

@ durron597谢谢。仍然是严格的输入,System.out使Java显得笨重;-)仍然感觉很好,已经发布了更长的答案。
TheConstructor 2014年

1
@ durron597,您专门要求一个功能,所以我认为它不算在内。如果我不得不使用导入,那可能是肯定的。
TheConstructor 2014年

1
至少每个变量都没有$ ;-)
TheConstructor 2014年

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


这对存在-2147483648有用吗?不太了解c编译器,无法告诉您将哪种整数类型分配给您的参数。
TheConstructor 2014年

感谢您指出。它适用于-2147483647 <= a <= 2147483647,与b相同。当a = -2147483648且b由于时为正时会出现问题a=-a
izabera

我尝试过,但最终得到了与您基本相同的解决方案。您可以通过实现printf("-")返回1 来保存一个字符
Thomas

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工作ca在每次迭代中将余数乘以10来工作。

演示


当a或b为负数时,会产生奇怪的结果
TheConstructor 2014年

我修复了负数错误。谢谢!
拉兹万2014年

刚找到您的代码的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 2014年

谢谢。我什至更新了您的版本,并设法赢得了额外的1个字节。
拉兹万2014年

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]

此解决方案不违反任何规定的规则。


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

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的c有用吗?
durron597 2014年

我用c = 1000进行了测试-代码给了我一个答案,也许我应该检查一下实际结果……
David Herrmann 2014年

2
g超越了大64位c?编辑:我认为您在BigInteger这里隐式使用
durron597

Err,g是一个字符串,但是在您致电之前,to_s您已经在内存中创建了一个大小超过64位的数字
durron597 2014年

1
这是可以理解的-使任务更具挑战性(也很有趣)!是删除答案还是让答案留给其他人看看如何不执行任务的示例更好?
David Herrmann 2014年

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:]

我认为更多打高尔夫球是可能的.....


2
e超越大型C 64位?编辑:我认为您在BigInteger这里隐式使用。
durron597 2014年

1
@ durron597我对此表示高度怀疑。转到BigInt(Python中的Long),但2 ** 45是48位。这足够吗?此外,python没有基元,所以……
Maltysen 2014年

如果a=5c=400再之后e=10**c,在十六进制数为333位长。它开始8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...超过64位。
durron597 2014年

@ durron597 400 ...我需要吗
Maltysen 2014年

1
是的,规则3表示您最多需要支持500个。...我试图防止这种解决方案。
durron597 2014年

1

C 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实现中使用的想法相同


非常好!但是,它崩溃了d(-2147483648,-1,10)
durron597
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.