Ocaml 如何打印无符号64位整数

Ocaml 如何打印无符号64位整数,ocaml,Ocaml,我要在Kattis身上解决这个问题 我已经在Python和C++中解决了,但是现在我想做OcAML。< /P> 这是我的密码: open Printf;; let rec gcd (a : int64) (b : int64) : int64 = if not (Int64.unsigned_compare b 0L > 0) then a else gcd b (Int64.unsigned_rem a b);; try whi

我要在Kattis身上解决这个问题

我已经在Python和C++中解决了,但是现在我想做OcAML。< /P> 这是我的密码:

open Printf;;

let rec gcd (a : int64) (b : int64) : int64 =
    if not (Int64.unsigned_compare b 0L > 0) then
        a
    else
        gcd b (Int64.unsigned_rem a b);;

try
    while true;
    do
        let line = read_line ()
        in
        if String.length line > 0 then
            let (nums : int64 list) = List.map (fun (s:string) : (int64) ->
                (Int64.of_string (Char.escaped '0' ^ Char.escaped 'u' ^ s ))) (String.split_on_char ' ' line)
            in
            let rec reduce (li : int64 list) (init : int64) : (int64) =
                match li with
                | [] -> init
                | head :: tail -> reduce tail ( Int64.unsigned_div (Int64.mul head init) (gcd head init) ) 
            in
            print_string ( Int64.to_string (reduce nums 1L) ^ "\n")
        else
            raise End_of_file
    done;
with End_of_file -> ();;
我可以通过第一个案例,但第二个(也是最后一个)案例的结果是错误的答案。这很奇怪,因为我的逻辑在我之前两次提交的不同语言中是相同的

我猜我打印的是错误的无符号64位整数:

print_string ( Int64.to_string (reduce nums 1L) ^ "\n")
早些时候,我试过:

printf "%Lu\n" (reduce nums 1L)
但是政府说

事实上,我并不认为这个警告与我的情况有关,但我仍然感到厌倦


有什么想法吗?谢谢你的阅读

你的代码适合我。您可以考虑从头开始重新启动OCAML,然后复制/粘贴上面的代码。我就是这么做的,这对我很有效

. . .
  with End_of_file -> ();;
2 3 5
30
1 2 3 4
12
399 772 163 959 242
832307365428

- : unit = ()
# 

我有一个64位系统,不管它值多少钱。也就是说,对于我来说,max_int是4611686018427387903。

466941151233371166不是任何输入的倍数,因此这显然是错误的。输入的数字相当大,所以我猜您只是有一个整数溢出。另一方面,你的C++代码表示1,它也不是任何一个NuMeBrs的倍数,而且也明显是错误的。 我可以看到一个可能是问题的地方:

( Int64.unsigned_div (Int64.mul head init) (gcd head init) )
当您处理输入时,
init
会越来越大,然后将其乘以下一个数字。只有在你把它除以GCD之后。在该步骤中,它暂时超过64位,而您将丢失位

根据GCD的定义,head和init都可以被它整除。那么,为什么不在乘法之前将其中一个除以GCD:

(Int64.mul init (Int64.unsigned_div head (gcd head init)))

这样,中间数永远不会大于结果,接近64位限制的结果仍然会产生正确的结果。

如果您给出了一个失败的示例输入,则会有所帮助。你链接到的页面上的所有示例都适用于我。也就是说,输出与链接页面上的输出相同。您的代码运行良好,我看不出任何不应该这样做的原因。关于printf,您应该使用
%Lu
修饰符。坏消息:我的代码仍然无法通过带有
printf
语句的Kattis测试用例。此外,为了让我们继续思考,Kattis不会分享它的测试用例。好消息:我在OCaml程序中运行了
123412341234 14441441 3555483355858858 345252345245
作为示例随机输入,然后返回
466941151233371166
。我为我成功的C++程序做了同样的输入,并获得了<代码> 1 <代码>。因此,我们确实以某种方式得到了错误的输出。这可能是因为OCaml中缺少一个易于使用的“大整数”库。请澄清,max_int不应该与该程序相关,因为它使用的int64总是64位的。当然,只要考虑可能的系统差异。感谢您的洞察力!我看到他们给出了不同的输出,立即认为OCaml是错误的。不幸的是,第二个测试用例在除法后相乘时仍然没有通过。因为
123412341234 14441441 3555483355858858345252345245
的最小倍数是
415670427229633820981190887227101634992940430
,它需要145位。仅仅64位是无法解决的。这个问题发生了什么?对于OCaml版本4.10.0,如何获取它?
(Int64.mul init (Int64.unsigned_div head (gcd head init)))