Crystal 中的类型规范

Type specification in Crystal

我是 Crystal 的新手,我正在尝试将以下程序翻译成 Crystal:

#include <stdio.h>

long rev(long n) {
  long m = 0;
  while (n > 0) {
    m = 10*m + n%10;
    n = n/10;
  }
  return(m);
}

int main() {
  for(int n=1; n<=10000000; n++) {
    long m = n*rev(n);
    if (m==rev(m))
      printf("%d\n", n);
  }
}

我写了Crystal程序

def rev(n : UInt64) : UInt64
  m : UInt64 = 0
  while n > 0
    m = 10_u64*m + n%10_u64
    n = n//10
  end
  m
end

(1_u64 .. 10_000_000).each { |n|
  m = n*rev(n)
  if m == rev(m)
    print(n,"\n")
  end
}

我发现奇怪的是,为了编译,在某些时候我必须指定文字的类型 (n%10_u64),但在其他地方则不需要 (n//10)。我是不是遗漏了什么,或者只是 Crystal 与演员表不一致?

此外,我想知道,这是一个很好的 c 程序翻译还是有经验的 Crystal 程序员会怎么做?

Crystal 中的默认数字类型是 Int32。因此,如果您不指定类型,就是这样。您的算法在 UInt64 上运行,因此您需要采取一些额外的步骤。

理想情况下,您会在算法中仅使用 UInt64 个数字,这样所有内容的输入都将相同。 但是您实际上不需要这样做,因为这些方法会强制转换操作数以适应。 return 类型始终是第一个操作数的类型。 UInt64#//(Int32) returns UInt64Int32#*(UInt64) returns Int32。但是,没有像C中那样的自动提升。

n // 10 很好,它 return 是 n 的类型,这正是您想要的。但是 10 * m 不好,因为它 return 是 10 的默认类型,即 Int32 并将其分配给 n 会改变其类型。

乍一看这似乎出乎意料,但 return 使用第一种类型的原因是允许像 x += y 这样的赋值运算符工作,它扩展到 x = x + y。如果 x + y return 是与 x 不同的类型,这将无意中影响变量的类型。

我的建议是将算法中的所有数字文字显式键入 UInt64 以确保它们适合在一起。