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
错误原因
- 换行符导致格式转换失败:你用
String.Join("\n", ...)拼接每行时,把换行符\n也包含进了最终字符串。当尝试将每个字符转成字符串再解析为int64时,换行符无法被解析为数字,直接抛出FormatException。 - 子序列长度不足:原
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
相关产品推荐
相关产品推荐

