诅咒的 Excel:为什么 "1/2"+1=45660?
- Pricing
- Product Pricing AI AnalysisChartsResearchComing soon Code PythonSQLFormulasJavaScript ConnectionsShow all PostgresMySQLSnowflake
- Solutions Use Cases Business IntelligenceProduct ManagementSales and MarketingFinance Enterprise Self-hosting DocsSelf-hosting Portal
- Resources Resources Quadratic 101TemplatesDocs Community About CompanyContactBlogChangelogTechnologyTrustCareers
- Open Quadratic
诅咒的 Excel:为什么 "1/2"+1=45660?
Andrew Farkas, Rust Developer
Apr 2, 2025
目录
Quadratic 的目标是成为最佳的用于数据分析的 AI spreadsheet,这意味着两个相互冲突的目标:
- 与 Microsoft Excel 保持功能对等
- 表现良好
我无意冒犯 Excel 的作者;它是一款出色的软件,我们在 Quadratic 经常将其誉为 spreadsheet 交互的黄金标准。也就是说,它今年已经 40 岁了,并且它的语义受到了数十年积累的向后兼容性补丁的影响。 我在这里工作最喜欢的事情之一就是我可以对 Excel 进行逆向工程,发现其行为中的奇怪之处,并决定在 Quadratic 中如何处理它们。我每天都在受苦,这样我们的用户就可以幸福地生活,而不会意识到 Microsoft 以兼容性为名犯下的未公开的罪行。今天,您将一窥我所面临的恐怖,然后您也将生活在对 Microsoft Excel 的恐惧中 - 不是因为您缺乏知识,而是因为您知道的太多了。
神奇的数字
多年来,遗传学家一直在与 Excel 过于热衷的日期解析作斗争,这种解析应用于像 MARCH1
或 SEPT2
这样并非旨在作为日期的名称。但 Excel 的日期解析器有更奇怪的边缘情况。
如果我们在单元格中输入 ="1/2"
,那么它当然包含文本“1/2”。
如果我们在此基础上加 1 呢?
45660?什么?? 提示:如果您将来尝试此操作,您可能会得到不同的数字。
而且不仅仅是日期!有时 Excel 的时间解析器会咬得比它能嚼的还要多一点。当然,在单元格中键入 10:25
会产生时间上午 10:25,但是如果键入 10:75
会发生什么呢?
0.46875??这又是从哪里来的?
我保证我会解释这里发生了什么,但首先我们需要介绍一些技术文档和天主教会历史。
(不要)阅读手册
在这两种情况下,我们都在欺骗 Excel 将我们的输入解析为日期或时间,但将其显示为数字。正如 DATEVALUE() 函数的官方文档解释的那样:
Microsoft Excel 将日期存储为连续的序列号,以便可以在计算中使用它们。默认情况下,1899 年 12 月 31 日的序列号为 1,而 2008 年 1 月 1 日的序列号为
39448
,因为它在 1900 年 1 月 1 日之后 39,448 天。 这很有帮助,但包含两个不准确之处。第一个是序列号1
代表 1900 年 1 月 1 日,而不是 1899 年 12 月 31 日。实际上,Excel 永远不会显示 1900 年之前的日期,而是坚持认为序列号0
代表 1900 年 1 月 0 日。值得庆幸的是,MONTH() 的文档 和许多其他函数中纠正了关于序列号 1 的错误,但仍然存在另一个不准确之处,而且它更加阴险。
实际上,1900 年 1 月 1 日和 2008 年 1 月 1 日之间只有 39,446 天,而不是 39,448 天。我可以理解差一错误,但为什么 Excel 差 2 呢? 想象一下,我正在为一周中的每一天分配一个数字。星期一是 1,星期二是 2,…,星期五是 5。但是您不会说星期五比星期一晚 5 天。它只晚 4 天,您可以通过从星期五的数字中减去星期一的数字来计算:5 - 1 = 4。这里也发生了同样的事情:要获得 1900 年 1 月 1 日和 2008 年 1 月 1 日之间的天数,我们应该真正从 2008 年的数字中减去 1900 年的数字:39448 - 1 = 39447。这更接近了,但仍然差 1。要理解剩余的差一错误,我们需要抓住我们的时间机器并穿越近 450 年。
日历系统
1582 年 10 月,教皇格雷戈里十三世 正式颁布,天主教会将使用由 Aloysius Lilius(当时已故)和 Christopher Clavius 开发的新的日历系统。儒略历 每 4 年有一个闰年,已经使用了 1600 多年,但造成了太多的偏移,以至于复活节已经与春分点不一致。新命名的 格里高利历 通过添加一条新规则纠正了偏移:每个可以被 100 整除的年份_都不是_闰年,除非可以被 400 整除的年份_仍然是_闰年。这就是为什么 2000 年是闰年(因为它可被 400 整除),但 1900 年不是。
1983 年,在新日历被采用近 400 年后,Lotus Software 发布了 Lotus 1-2-3,这是一款革命性的 spreadsheet + 数据库 + 图表程序。不幸的是,1582 年颁布的消息尚未传到 Lotus 1-2-3 的开发人员那里,因此他们认为 1900 年(是 4 的倍数)是闰年。几年后,Microsoft 发布了第一个版本的 Excel,其中包含相同的错误闰年。如果在 Excel 中输入 Feb 28, 1900
并加 1,您将得到 Feb 29, 1900
——一个从未发生过的日子,但为了与 Lotus 1-2-3 保持兼容性,这是必要的。
这解释了 Excel 文档中的另一个差一错误;Excel 在 1900 年 2 月多计算了一天,因此该日期之后的日期的序列号比您预期的要大 1。
发生了什么?
当您仍然理智时,我承诺解释为什么 "1/2"+1
等于 45660
以及为什么 Excel 将 10:75
变成了 0.46875
。
一旦您意识到 Excel 将 1/2 解析为 2025 年 1 月 2 日(我写这篇文章的年份),第一个实际上应该有意义。当我们加 1 时,我们得到 2025 年 1 月 3 日,并且在那一天和 1900 年 1 月 1 日之间有 45,658 天。由于前面描述的原因,加 2,我们得到 45,660,这正是 Excel 所说的。我不知道它为什么显示一个数字而不是一个日期,但至少这个数字是有意义的。
第二个需要深刻的哲学见解:时间是什么,而不是一天中的一部分? 例如,早上 6:00 是 0.25 天,因此 Excel 使用数字 0.25
表示它。按照这个逻辑,0.46875
应该代表上午 11:15,这比上午 10:00 晚 75 分钟,所以如果你不仔细考虑,这有点像上午 10:75。但是在内心深处,Excel 知道这是非常错误的,因此它将其显示为一个数字。
我们甚至可以使用大于 23 的小时数来获得晚上 11:59 之后的时间。在单元格中键入 37:30
会产生数字 1.5625
,它代表_第二天_下午 1:30。数字 1 代表 1900 年 1 月 1 日开始时的午夜,因此 1.5625
代表 1900 年 1 月 1 日下午 1:30。
Google Sheets 怎么样?
Google Sheets 有一个绝妙的主意,通过将 1900 年的前两个月移动一位来删除 1900 年 2 月 29 日,因此它使用序列号 2
而不是 1
来表示 1900 年 1 月 1 日。这是一个非常聪明的解决方案,尽管从 2
开始有点尴尬,并且从 Excel 导入时,会导致 1900 年 3 月 1 日之前的日期偏差 1。
Quadratic 怎么样?
我们正在从头开始构建 Quadratic,以与 Python、SQL、JavaScript 和其他现代编程和数据库工具配合使用,因此不正确的日历系统不是一种选择。我们使用经过实战考验的 chrono 库来处理 Rust 中的日期时间,它与 Python 的内置 datetime 库以及其他语言中的类似数据类型配合良好。当从 Excel 导入文件时,我们将所有具有日期格式的单元格转换为相应的日期时间。为了恢复宇宙的平衡,1900 年 2 月 29 日被转换为 1900 年 2 月 28 日。
使用正确的日期时间系统 还有一个额外的好处,就是让我们能够表示比 1900 年早得多的日期,尽管我会小心处理 1582 年之前的任何日期。从头开始构建 Excel 的替代品 具有挑战性,并且需要很长时间才能做好,因此如果您有我们尚不支持的用例,请在我们的社区论坛上告诉我们,或者在 GitHub 上提交代码贡献!
The spreadsheet with AI.
-
Spreadsheet
-
-
Code
-
-
Connections
-
Product AI AnalysisChartsResearch Code PythonSQLFormulasJavaScript Connections PostgresMySQLSnowflake
-
Solutions Use Cases Business IntelligenceProduct ManagementSales and MarketingFinance Enterprise Self-hosting DocsSelf-hosting Portal
-
Resources Resources Quadratic 101TemplatesDocs Community About CompanyPricingBlogChangelogTechnologySecurity Careers
-
ConnectYoutube ContactPartnersAdvocates Compliance Privacy policyTerms and conditionsTrust Status
© 2025 Quadratic Growth Inc.