将分数转换为重复的小数


17

如果遇到这种挑战,几乎是两极对立的,我怀疑这会稍微容易一些。

您的任务是采用格式为2的两个整数a/b(形成一个有理数),然后精确输出十进制数。

例如,如果要输入1/3,它将输出:

0.33333333333333333

并且将持续打印3s直到时间结束,并带有可选的前导0。(如果且仅当您的语言不允许在同一行上打印时,您才可以每行打印一个字符。)

的行为x/0将是不确定的。对于看起来不重复的数字(例如说5/4),它实际上确实重复。以下两种形式均可以接受5/4

1.25000000000000000
1.24999999999999999

(与整数相同,1.99999992.000000

分数可能无法在其最简单的形式,和ab可能是负的(注-a/b = -(a/b)-a/-b = a/ba/-b = -a/b,和-.6249999是无效的,但是-0.6249999是可以接受的,但你仍然可以使用。


我们可以使用Unix bc还是作弊?
David R Tribble 2015年

在我继续打高尔夫球之前,我的回答是:可以a和/或是b否定的?
丹尼斯

@Dennis是的,但是一个a或一个b(或两个都可以是负数)

@DavidRTribble我认为这是一个标准漏洞,所以没有。

您最近的编辑是否说带零的前导零是可以的,但带负数的不是零?如果是这样,那是什么原因呢?
Geobits,2015年

Answers:


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 2015年

@orlp:完全。现在已修复。
丹尼斯2015年

6

C,108 79

编辑修改为使用负数。

来自stdin的输入。旧的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

Ruby 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 2015年

哇,我刚刚学到了很多东西,谢谢!我不记得?/要表示字符,也不知道$><<要打印或loop关键字。非常感谢!!
rorlork 2015年

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
如果您仍然感兴趣,那么自ruby 2.1(我在10分钟前了解到)以来,还有一个合理的文字Rational(2,3) == 2/3r)可用于缩短第二行:eval(s+?r)<0&&$><<?-
blutorange

2

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

尽管输出确实有刷新问题,但我能够通过休眠9ms来获取输出以显示输出,这将节省两个字节。

@Snowman可能取决于硬件或操作系统;我的计算机不能在少于250ms的时间内运行。
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/3-> -0.
  • 取绝对值*
  • 环:
    • 分子除以分母后的余数
    • 分子乘以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

编辑:

现在按照要求在同一行上输出所有字符。

编辑2:

现在按要求从命令行参数读取分数:)


1
一些提示:1)使用map而不是列表理解可以节省很多时间;2)不需要的括号m*a中的任何位置,如*%/都是相同的优先级和左结合; 3)第3行的0点逻辑可以简化为"0."[m==1],因为无论如何您都只是在打印它;4)可能会保存char以便仅根据需要设置字符o=stdout.write并将其转换为带反引号的字符串
DLosc

1
另外,该代码似乎不适用于底片:1/-3给出-1.666666666而不是-0.333333333
DLosc
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.