You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

F#读取含换行符的文本文件时出现格式转换错误问题

解决Project Euler #8的F#代码格式转换错误

问题描述

我在完成Project Euler第8题时,用F#编写代码读取一个被换行符分隔的1000位大数字,但即使拼接字符串后仍出现格式转换错误,两种处理方式得到相同的报错信息。

原代码

open System;
open System.Text;

let path = "/Users/Arbin/Desktop/VS Code/F#/Project Euler/Largest Product in Series/largest_product_text_file"
//let monster_number = System.IO.File.ReadAllText path
let monster_number_array = System.IO.File.ReadAllLines path

let monster_number = String.Join("\n", System.IO.File.ReadAllLines path);


printfn "%s" monster_number

let adjacent n seq =
    seq |> Seq.mapi (fun index value -> seq |> Seq.skip index |> (Seq.truncate n))

//Mapping numbers from string to integer64.
let seq_of_seq = (adjacent 13 monster_number) |> Seq.map (Seq.map (int64 << string))

//Iterating through a sequence of sequence (nested sequence)
seq_of_seq |> Seq.iter (fun x -> x |> Seq.iter (fun y -> printfn "Ar: %A" y))

错误输出

<Sequence Integers>
System.FormatException: Input string was not in a correct format.
   at Microsoft.FSharp.Core.LanguagePrimitives.ParseInt64(String s) in D:\a\_work\1\s\src\FSharp.Core\prim-types.fs:line 2414
   at Microsoft.FSharp.Collections.Internal.IEnumerator.map@99.DoMoveNext(b& curr) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 102
   at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator`1.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 84
   at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 596
   at FSI_0001.it@20.Invoke(IEnumerable`1 x) in /Users/Arbin/Desktop/VS Code/F#/Project Euler/Largest Product in Series/largest_product_in_series.fsx:line 20
   at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 597
   at <StartupCode$FSI_0001>.$FSI_0001.main@() in /Users/Arbin/Desktop/VS Code/F#/Project Euler/Largest Product in Series/largest_product_in_series.fsx:line 20
Stopped due to error

待读取的数字内容

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

错误原因

  1. 换行符导致格式转换失败:你用String.Join("\n", ...)拼接每行时,把换行符\n也包含进了最终字符串。当尝试将每个字符转成字符串再解析为int64时,换行符无法被解析为数字,直接抛出FormatException。
  2. 子序列长度不足:原adjacent函数会生成长度不足13的子序列(当索引接近序列末尾时),虽然这不会直接报错,但不符合题目中“连续13个数字”的要求。

修正后的代码

open System

let path = "/Users/Arbin/Desktop/VS Code/F#/Project Euler/Largest Product in Series/largest_product_text_file"

// 读取文件内容并过滤掉所有非数字字符,得到纯数字字符串
let monster_number = 
    File.ReadAllText path
    |> Seq.filter Char.IsDigit
    |> Seq.toArray
    |> String

printfn "处理后的纯数字字符串:%s" monster_number

// 生成所有长度为n的连续子序列
let adjacent n (seq: seq<'a>) =
    let arr = seq |> Seq.toArray
    [ for i in 0 .. arr.Length - n -> arr.[i..i+n-1] |> Seq.ofArray ]

// 将字符直接转换为int64(利用ASCII值计算,避免字符串解析错误)
let seq_of_seq = adjacent 13 monster_number |> Seq.map (Seq.map (fun c -> int64 (c - '0')))

// 计算所有连续13个数字的乘积,找出最大值
let max_product =
    seq_of_seq
    |> Seq.map (Seq.fold (*) 1L)
    |> Seq.max

printfn "最大乘积:%d" max_product

修正说明

  • 过滤非数字字符:用Seq.filter Char.IsDigit直接去掉换行符和其他可能的非数字字符,确保最终字符串只有数字。
  • 优化子序列生成:先将序列转为数组,通过循环生成刚好长度为13的子数组,避免处理无效的短序列。
  • 高效字符转数字:利用字符的ASCII值差(c - '0')直接得到数字,比转成字符串再解析更高效,也彻底避免了格式错误。

内容的提问来源于stack exchange,提问作者ArbIn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:25:19