周一上线了一个天气仪表盘,周三就收到了多伦多用户的 bug 报告:界面显示的室外温度是 284。OpenWeatherMap 的接口默认返回开尔文(Kelvin),前端却按摄氏度处理,中间一层都没人去校验单位。少做了一次减法,换来推特上的一张翻车截图。
如果你只想拿到公式、马上走人,那看这三行就够:
- 摄氏转华氏公式:
°F = °C × 9/5 + 32 - 华氏转摄氏公式:
°C = (°F − 32) × 5/9 - 摄氏转开尔文:
K = °C + 273.15
这三条大约能覆盖开发者 90% 的实际需求。本文剩下的内容就是那另外 10%:9/5 从哪儿来、为什么开尔文永远不会是负值、如何让类型系统在编译期就拒绝 celsiusToFahrenheit(kelvinValue) 这种调用、以及怎么彻底杜绝开头那种「多伦多 bug」。当然你也可以完全跳过阅读,直接使用我们的温度换算工具拿到结果。如果你要处理的是温度以外的单位,请参考更全面的单位换算完全指南。
温度为什么和其他单位换算不一样
大多数单位换算都是过零点的纯线性关系。1 米等于 3.28084 英尺,就这一句话。米数加倍,英尺数也加倍;零米就是零英尺。你只需要为每对单位记一个乘法常数,一个换算库就能用到天荒地老。
温度在一个关键点上打破了这个模型:不同温标的零点不一致。摄氏的零点锚在水的冰点,华氏的零点锚在 1724 年丹齐格的某种盐水混合物上,开尔文的零点锚在热力学的理论下限。要在任意两者之间换算,你需要的不只是一个缩放因子,还得加上一个偏移量。换句话说,温度变换是仿射(affine)而不是线性(linear)。
这带来一个具体且危险的后果:温度值不是可相加的量,它和长度、质量不同。20°C + 20°C 在任何物理意义上都不等于 40°C。你不能把「两个房间加起来」得到一个更热的房间。但你可以把一个温度差加到一个温度上,因为差值本身是线性的。2006 年英国 Medeva 疫苗冷链事故就栽在这个区分上:某个温度记录仪把绝对读数当成了温差,结果把数千支疫苗错误判定为超规。像温度这样的强度量(intensive quantity)得时刻在心里留一条护栏:共享单位的数字,未必共享相同的代数规则。
四种温标详解
日常代码真正会用到的温标只有两个(摄氏、华氏),涉及科学场景时要加上第三个(开尔文),第四个只会在一个地方出现:美国热力学教科书以及至今仍在引用它们的 HVAC 代码库。
摄氏(Celsius,°C)
Anders Celsius 在 1742 年发表了他的温标,最初 0° 表示沸点、100° 表示冰点,和今天的方向正好相反。现代的定义(0°C 为水在 1 个标准大气压下的冰点,100°C 为沸点)是在他去世后不久确立的。今天它是日常温度的 SI 导出单位,除了美国、巴哈马、伯利兹、开曼群岛和利比里亚,其他国家都以它为默认温标。
2019 年 SI 重新定义把摄氏严格绑定到了开尔文(Kelvin):现在 0°C 被精确地定义为 273.15 K。水的冰点从曾经的定义,变成了一个测量结果(实测值在百万分之几以内落在 0°C,但它不再是定义锚点)。
华氏(Fahrenheit,°F)
Daniel Gabriel Fahrenheit 在 1724 年提出了他的温标。他把 0°F 定为某种特定盐水混合物的冰点(丹齐格的冬天里他能稳定复现的最低温度),把 96°F 定为人体温度。后来以纯水的冰点和沸点重新校准,人体温度被推到 98.6°F,冰点落在 32°F,沸点落在 212°F,中间正好跨越 180 度。
华氏在美国的天气预报、烹饪和医疗场景中仍在使用。有人为它辩护说,冰点到沸点之间跨越 180 度(相比摄氏的 100 度)可以「为常温段提供更细的分辨率」。这个论点站得不太稳,但可以解释为什么美国的恒温器以 1°F 为步进,欧洲的则常见 0.5°C 步进。
开尔文(Kelvin,K)
William Thomson,即开尔文勋爵(Lord Kelvin),在 1848 年提出了绝对温标。现代的开尔文是温度的 SI 基本单位。2019 年 SI 重新定义把开尔文精确绑定到玻尔兹曼常数 k_B = 1.380649 × 10⁻²³ J/K,使它从一个测量量变成了一个定义量。
开尔文有三个开发者必须清楚的小癖好:
- 不写度符号。 写作
300 K,不是300°K。这是 SI 自 1967 年以来的约定。 - 起点是绝对零度。
0 K = −273.15°C。在合规数据里你永远不应该看到负的开尔文值;一旦看到,当作输入错误处理。 - 与摄氏同样的度数大小。 1 K 的变化等于 1°C 的变化。温度差在两者之间可以互换;只有绝对值相差 273.15 的偏移量。
只要你需要对温度做乘除或求幂运算,就该用开尔文:热辐射(T⁴)、理想气体状态方程、黑体物理都属于这一类。对接近零或负的摄氏值做除法,会让本应有限的物理量瞬间崩溃。
兰氏(Rankine,°R)
William Rankine 在 1859 年提出了这个温标,它是华氏版的开尔文:绝对温标,零点落在绝对零度,但使用华氏大小的度数。0°R = −459.67°F,491.67°R = 0°C。
除了美国的热力学工程领域(HVAC 计算、石油精炼、火箭发动机燃烧分析),你基本不会遇到兰氏。这些场景需要绝对温标,而原始数据又恰好以华氏输入。换算本身很机械:°R = °F + 459.67,或等价地 °R = K × 9/5。大多数现代工程软件其实可以在内部一直使用开尔文,只在显示时才转换。这也是你有选择权时我建议的做法。
六个方向的温度换算公式
四种温标、六个方向、六个公式。实际操作中,你只要记住以摄氏为中心的几条,其他都可以组合得到。
摄氏和华氏互换
°F = °C × 9/5 + 32
°C = (°F − 32) × 5/9
9/5 这个系数来自两种温标在相同两个物理标志点之间跨度的比值。从冰点到沸点,华氏跨了 180 度(32 到 212),摄氏跨了 100 度(0 到 100)。180 / 100 = 9/5 = 1.8。+ 32 是对齐冰点零点所需的偏移量,因为华氏的零点位于摄氏零点以下 32°F。
算一个:°F = 25 × 9/5 + 32 = 45 + 32 = 77°F。
摄氏和开尔文互换
K = °C + 273.15
°C = K − 273.15
没有缩放,只有偏移。273.15 是摄氏的零点(水的冰点)向下到绝对零度的数值距离,以摄氏度为单位度量。因为开尔文与摄氏共享相同的度数大小,所以不需要乘数。
华氏和开尔文互换
K = (°F − 32) × 5/9 + 273.15
°F = (K − 273.15) × 9/5 + 32
没有更短的写法,既要换尺度又要换零点。在代码里,中转一次摄氏几乎总是更干净:k = cToK(fToC(f))。写得更少也更可信赖,而且编译器反正会把这层组合优化掉。
兰氏换算
°R = °F + 459.67
°F = °R − 459.67
°R = K × 9/5
K = °R × 5/9
°R = °C × 9/5 + 491.67
491.67 就是 32 × 9/5 + 459.67,也就是 0°C 对应的兰氏值。实际工程中你很少需要把这些公式串联起来。真遇到兰氏的时候,把它视作「华氏的绝对版双胞胎」,通过华氏或开尔文中转就好。
9/5 是怎么来的?一段简短的推导
两种温标之间的关系是一个仿射函数 °F = a × °C + b。要解出 a 和 b,需要两个已知的标定点。冰点和沸点是传统的组合:
- 冰点:
0°C ↔ 32°F - 沸点:
100°C ↔ 212°F
代入 °F = a × °C + b:
32 = a × 0 + b → b = 32
212 = a × 100 + 32 → a = (212 − 32) / 100 = 180 / 100 = 9/5
就这样,两条一次方程、两个未知数,整套换算全掉出来了。几何直觉是这样的:想象两支垂直的温度计并排摆放,一支摄氏、一支华氏。相对于摄氏那支,华氏那支在竖直方向上被拉伸(斜率 9/5)并向上平移(截距 32)。每一个其他换算点都落在那条被拉伸、被平移的直线上。
用 (0°C, 273.15 K) 和 (100°C, 373.15 K) 走一遍相同的推导,就得到摄氏到开尔文的换算:斜率 1,截距 273.15。任意选两个明确的标定点,都可以得到对应的仿射换算。温度在数学上并没有什么特殊之处。所有复杂性都集中在「两个锚点」这套设定上,其他单位类型不需要这一步。
−40° 交点:一个实用的记忆法
有没有一个温度,摄氏和华氏读数相同?把 °C = °F 代入换算公式:
°C = °C × 9/5 + 32
°C − °C × 9/5 = 32
°C × (1 − 9/5) = 32
°C × (−4/5) = 32
°C = −40
于是 −40°C = −40°F。有且仅有一个交点,而且它恰好是现实中真会遇到的温度:一月的黄刀镇(Yellowknife)、雅库茨克(Yakutsk)或费尔班克斯(Fairbanks)就长这样。这也是一个便宜的心算校验:当你目测一个 C↔F 换算、结果接近 −40 时,两个数字应当彼此接近。如果一个写着 −40°C、另一个写着 −72°F,那你八成把方向搞反了。
我在显示器旁贴了一份完整的记忆点清单:冰点(0 / 32)、体温(37 / 98.6)、室温(20 / 68)、沸点(100 / 212)、−40(−40 / −40)。五个点已经覆盖了我几乎所有需要心算验证的场景。
温度换算代码实现
公式本身很简单。在真实代码库里要把它们做对,主要就做两件事:阻止调用者把华氏传到期望摄氏的地方,以及让浮点行为在临界点(冰点、绝对零度、烤箱温度)上可预测。下面每个示例都是一份完整、可运行的程序。
JavaScript / TypeScript
普通 JavaScript 立刻就能实现函数式的换算:
const cToF = (c) => c * 9 / 5 + 32;
const fToC = (f) => (f - 32) * 5 / 9;
const cToK = (c) => c + 273.15;
const kToC = (k) => k - 273.15;
const fToK = (f) => cToK(fToC(f));
const kToF = (k) => cToF(kToC(k));
const cToR = (c) => (c + 273.15) * 9 / 5;
const rToC = (r) => r * 5 / 9 - 273.15;
console.log(cToF(100)); // 212
console.log(fToC(98.6)); // 37
console.log(kToC(300)); // 26.85
TypeScript 可以通过给数字类型打品牌(branded type)让单位混用变成编译错误:
type Scale = 'C' | 'F' | 'K' | 'R';
type Temp<S extends Scale> = number & { readonly __scale: S };
const t = <S extends Scale>(value: number, _scale: S): Temp<S> =>
value as Temp<S>;
const cToF = (c: Temp<'C'>): Temp<'F'> => t(c * 9 / 5 + 32, 'F');
const fToC = (f: Temp<'F'>): Temp<'C'> => t((f - 32) * 5 / 9, 'C');
const indoor = t(22, 'C');
const outdoor = cToF(indoor); // OK:Temp<'F'>
// const broken = cToF(outdoor); // 编译错误:Temp<'F'> 不是 Temp<'C'>
品牌类型没有运行时开销,代价大概是十行样板代码。换来的是:开头段落里那个多伦多 bug,会在你编辑器里变成一条红色波浪线。
Python
普通函数就能用,但一旦要打印温度日志,Enum 搭配 dataclass 立刻就回本了:
from dataclasses import dataclass
from enum import Enum
class Scale(Enum):
C = "°C"
F = "°F"
K = "K"
R = "°R"
@dataclass(frozen=True)
class Temperature:
value: float
scale: Scale
def to(self, target: Scale) -> "Temperature":
c = _to_celsius(self)
return _from_celsius(c, target)
def __str__(self) -> str:
return f"{self.value:.2f}{self.scale.value}"
def _to_celsius(t: Temperature) -> float:
if t.scale is Scale.C: return t.value
if t.scale is Scale.F: return (t.value - 32) * 5 / 9
if t.scale is Scale.K: return t.value - 273.15
if t.scale is Scale.R: return (t.value - 491.67) * 5 / 9
raise ValueError(f"未知温标:{t.scale}")
def _from_celsius(c: float, scale: Scale) -> Temperature:
if scale is Scale.C: return Temperature(c, scale)
if scale is Scale.F: return Temperature(c * 9 / 5 + 32, scale)
if scale is Scale.K: return Temperature(c + 273.15, scale)
if scale is Scale.R: return Temperature(c * 9 / 5 + 491.67, scale)
raise ValueError(f"未知温标:{scale}")
body = Temperature(37, Scale.C)
print(body.to(Scale.F)) # 98.60°F
print(body.to(Scale.K)) # 310.15K
如果你处理的是科学数据、0.1 + 0.2 != 0.3 都会被审计盯上,那就把 float 换成 decimal.Decimal。代价是速度(Decimal 大约慢 50 倍),而且 5/9 在十进制里同样没有精确表示,所以你得用带上下文控制的 Decimal(5) / Decimal(9)。对大多数传感器管线来说,float 加上在显示边界做 round(value, 2) 已经绰绰有余。
Go
Go 的类型系统能走得比 TypeScript 更远:两个同样底层的 float64 命名类型,在编译期就不允许互相隐式混用,尽管它们的运行时表示一样。
package main
import "fmt"
type Celsius float64
type Fahrenheit float64
type Kelvin float64
type Rankine float64
func (c Celsius) ToFahrenheit() Fahrenheit { return Fahrenheit(c*9/5 + 32) }
func (c Celsius) ToKelvin() Kelvin { return Kelvin(c + 273.15) }
func (f Fahrenheit) ToCelsius() Celsius { return Celsius((f - 32) * 5 / 9) }
func (k Kelvin) ToCelsius() Celsius { return Celsius(k - 273.15) }
func (f Fahrenheit) ToKelvin() Kelvin { return f.ToCelsius().ToKelvin() }
func main() {
room := Celsius(22)
fmt.Printf("%.2f °F\n", room.ToFahrenheit()) // 71.60 °F
fmt.Printf("%.2f K\n", room.ToKelvin()) // 295.15 K
// var bug Fahrenheit = room // 编译错误
// fmt.Println(room.ToKelvin() + 1) // 编译错误:Kelvin + 无类型 int 需要写 Kelvin(1)
}
成本大致是每个温标多一行代码。收益是:ToFahrenheit 不可能误接一个开尔文值,接收 Celsius 参数的函数会在调用处直接拒绝裸 float64。
Rust
Rust 的 newtype 模式能提供和 Go 相同的保证,外加廉价的 From/Into 转换:
#[derive(Clone, Copy, Debug, PartialEq)]
struct Celsius(f64);
#[derive(Clone, Copy, Debug, PartialEq)]
struct Fahrenheit(f64);
#[derive(Clone, Copy, Debug, PartialEq)]
struct Kelvin(f64);
impl From<Celsius> for Fahrenheit {
fn from(c: Celsius) -> Self { Fahrenheit(c.0 * 9.0 / 5.0 + 32.0) }
}
impl From<Fahrenheit> for Celsius {
fn from(f: Fahrenheit) -> Self { Celsius((f.0 - 32.0) * 5.0 / 9.0) }
}
impl From<Celsius> for Kelvin {
fn from(c: Celsius) -> Self { Kelvin(c.0 + 273.15) }
}
impl From<Kelvin> for Celsius {
fn from(k: Kelvin) -> Self { Celsius(k.0 - 273.15) }
}
fn main() {
let body = Celsius(37.0);
let body_f: Fahrenheit = body.into();
let body_k: Kelvin = body.into();
println!("{:.2} {:?} {:?}", body.0, body_f, body_k);
// 37.00 Fahrenheit(98.6) Kelvin(310.15)
}
你可以在上面叠加校验:实现一个 TryFrom<f64> for Kelvin 来拒绝负值,返回 Result<Kelvin, TemperatureError>,把校验逻辑前移到构造阶段。非法状态永远进不了业务逻辑。
SQL(PostgreSQL)
存储温度时用 CHECK 约束,并把备用温标作为生成列(generated column)派生出来。这样一来,负开尔文值会在插入时就触发约束违例,而不是在三层查询之后才暴露成一条静默的数据 bug。
CREATE OR REPLACE FUNCTION c_to_f(c numeric) RETURNS numeric AS $$
SELECT c * 9.0 / 5.0 + 32.0;
$$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION c_to_k(c numeric) RETURNS numeric AS $$
SELECT c + 273.15;
$$ LANGUAGE SQL IMMUTABLE;
CREATE TABLE sensor_readings (
id bigserial PRIMARY KEY,
recorded_at timestamptz NOT NULL DEFAULT now(),
celsius numeric(6, 2) NOT NULL,
fahrenheit numeric(6, 2) GENERATED ALWAYS AS (c_to_f(celsius)) STORED,
kelvin numeric(6, 2) GENERATED ALWAYS AS (c_to_k(celsius)) STORED,
CONSTRAINT kelvin_non_negative CHECK (celsius >= -273.15)
);
INSERT INTO sensor_readings (celsius) VALUES (22.5), (0), (100);
SELECT celsius, fahrenheit, kelvin FROM sensor_readings;
-- 22.50 | 72.50 | 295.65
-- 0.00 | 32.00 | 273.15
-- 100.00| 212.00 | 373.15
-- 插入时直接被拒绝:
-- INSERT INTO sensor_readings (celsius) VALUES (-300);
-- ERROR: new row for relation "sensor_readings" violates check constraint
GENERATED ALWAYS AS ... STORED 用一点磁盘空间换查询期速度:读取时直接返回值,不重新计算。对高流量的 IoT 表,如果磁盘压力比读延迟更重要,就把 STORED 换成视图。
处理天气与 IoT API
温度在生产环境里最常见的 bug 不是公式写错,而是接口返回的单位和 UI 显示的单位不一致。简单扫一遍开发者最常碰到的几家服务:
OpenWeatherMap 默认返回开尔文。传 units=metric 得到摄氏,传 units=imperial 得到华氏。关键点在于:如果你忘了这个查询参数,你会拿到开尔文。名字叫 temp 的字段里返回 284.15 这种数字,已经骗过了足够多工程师,值得为它写一个集成测试。
Open-Meteo 默认返回摄氏,支持 temperature_unit=fahrenheit,不提供开尔文选项(它不是科学类 API)。
Tomorrow.io 和 WeatherAPI 默认使用公制,但会在同一份响应里用不同的键名同时返回两种温标。读你代码里明确引用的那个键,不要图省事读旁边那个。
我在任何天气或传感器数据摄取场景里都会用下面这个模式:
type Reading = {
value: number;
scale: 'C' | 'F' | 'K';
source: string;
};
function normalise(raw: Reading): number /* 摄氏 */ {
switch (raw.scale) {
case 'C': return raw.value;
case 'F': return (raw.value - 32) * 5 / 9;
case 'K': return raw.value - 273.15;
}
}
// 在摄取阶段,每条读数都显式携带自己的温标。
// UI 层永远不猜测——它只消费摄氏值,再按用户偏好格式化。
由此派生出两条规则:
- 每一个摄取边界都要记录来源温标。没有裸数字能跨越模块边界。
- 显示层是唯一会把数值转换到用户偏好单位的地方。
另一个高频 bug 是重复转换:两层代码都「好心地」规范化了同一个数字。后端团队在写入时把开尔文转成了摄氏,前端团队毫不知情又在读取时减了一遍 273.15。用户看到的温度大概是 −251°C。解法是为规范化指定一个唯一负责人,而不是加更多测试。
对 IoT 场景,传感器的原始信号常常是一个必须经标定曲线才能换算为温度的 ADC 计数(比如 10kΩ 的 NTC 热敏电阻要用 Steinhart–Hart 方程)。温标之间的换算发生在那之后,作用在已标定过的数值上。把这两个阶段搅在一起,就会得到一组看起来像温度、实则偏差 30% 的数字。
常见陷阱及其规避
下面这六种陷阱在真实的生产代码库里反复出现。对照检查一下你的代码。
公式方向反了
最常见的表现:某个 App 显示婴儿「发烧 37°C」,然后把它标记为危急。实际发生的是:API 返回的是 37°F,有人因为列名写着 celsius 就按摄氏理解,医疗阈值逻辑又是按摄氏比较的。防止这种 bug 的办法是让类型而不是变量名来承载单位。
把温度当作外延量
averageTemperature(平均温度)有意义,sumTemperatures(温度之和)没有。如果你的聚合 SQL 出现 SUM(temperature_c),大概率是错的:你多半想要 AVG,偶尔会用到积分型的度日(degree-day)指标。温度是强度量(intensive quantity);把两个温度加起来,期望拿到一个有意义的结果,是走不通的。
浮点舍入
JavaScript 里 (37 * 9 / 5) + 32 得到的是 98.60000000000001,不是 98.6。任何使用 IEEE 754 双精度浮点的语言都会给你同样的结果。处理选项:
- 用
.toFixed(2)(或你所用语言的等价函数)做展示,到此为止。 - 用十进制库(
decimal.js、Python 的Decimal、BigDecimal)做审计级精度。 - 以「十分之一度」为单位存成整数(比如用
370表示37.0),只在显示边界做除法。
对 UI 显示来说,toFixed(2) 几乎总是正确的。对计费或监管系统这种舍入误差会累积的地方,请使用十进制。
缺少对负开尔文的输入校验
开尔文按物理定律不可为负。含 { "tempK": -10 } 的请求体永远是非法的。在边界上拦住它(JSON schema、Pydantic、Zod、CHECK 约束),不要等到业务逻辑深处才发现。唯一的例外是量子系统里的「负绝对温度」,这种东西不会出现在你会对接的任何 API 里;真遇到了,你自己已经知道会遇到。
UI 和日志里缺单位标注
一条写着 sensor 42: 37 的日志,半年后再看毫无用处。那是摄氏?华氏?还是一个 ADC 原始计数?始终写成 sensor 42: 37°C,或者把日志结构化成 { "sensor": 42, "value": 37, "unit": "celsius" }。磁盘很便宜,凌晨三点排查生产故障不便宜。
时区混淆连累温度
旅行类 App 偶尔会栽一个跟头:用户跨时区后,代码「好心」地把所有带时间戳的字段都做了时区偏移,连温度读数也不放过。温度不关心时区。读数上附带的时间戳需要时区逻辑,读数的数值不需要。把它们放在不同字段里,走不同的转换管线。
心算捷径
在手边没有换算器的时候用。
摄氏→华氏(粗略): 翻倍再加 30。20°C → 70°F(实际 68)。30°C → 90°F(实际 86)。在 0–40°C 区间里精度在 2–3°F 以内,除了窑炉,这已经覆盖了你日常体感到的几乎所有温度。
华氏→摄氏(粗略): 减 30 再折半。80°F → 25°C(实际 26.7)。60°F → 15°C(实际 15.6)。精度带宽一致。
摄氏→开尔文: 加 273 取整。丢了 0.15 K,这低于物理实验室之外任何温度计的精度。
两个值得记住的锚点: 20°C = 68°F ≈ 293 K,以及 100°C = 212°F = 373.15 K。从这两个点出发做线性插值,任何估算都能差不多落得住。
粗快速算法能应付旅行、粗略下厨、看天气预报。要写进代码或递交监管文件的场合,请用精确公式,或者打开我们的免费温度换算工具复制出精确值。
参考对照表
日常温度
| 场景 | 摄氏 | 华氏 | 开尔文 |
|---|---|---|---|
| 家用冷冻柜 | −18°C | 0°F | 255.15 K |
| 水的冰点 | 0°C | 32°F | 273.15 K |
| 冰箱冷藏 | 4°C | 39°F | 277.15 K |
| 室温 | 20°C | 68°F | 293.15 K |
| 体温 | 37°C | 98.6°F | 310.15 K |
| 发烧阈值 | 38°C | 100.4°F | 311.15 K |
| 炎热夏日 | 35°C | 95°F | 308.15 K |
| 水的沸点 | 100°C | 212°F | 373.15 K |
烹饪与烤箱换算
| 烤箱档位 | 摄氏 | 华氏 |
|---|---|---|
| 低温 / 慢烤 | 125°C | 257°F |
| 温热烘焙 | 150°C | 302°F |
| 中等烘焙 | 175°C | 347°F |
| 常规烘焙(蛋糕) | 180°C | 356°F |
| 烤肉 | 190°C | 374°F |
| 高温烤肉 | 200°C | 392°F |
| 猛火烤肉 | 220°C | 428°F |
| 披萨 / 面包脆皮 | 250°C | 482°F |
美国食谱里的 350°F 有时写成 175°C、有时写成 180°C,取决于菜谱作者,精确值是 176.67°C。选哪个都行:家用烤箱的温度稳定度一般连 ±5°C 都做不到。
科学极端值
| 现象 | 开尔文 | 摄氏 |
|---|---|---|
| 绝对零度(理论下限) | 0 K | −273.15°C |
| 宇宙微波背景辐射 | 2.725 K | −270.425°C |
| 液氦(沸点,1 atm) | 4.2 K | −268.95°C |
| 超导体转变温度(YBCO) | 93 K | −180.15°C |
| 液氮(沸点) | 77 K | −196.15°C |
| 深空阴影 | 约 40 K | 约 −233°C |
| 干冰(升华) | 194.65 K | −78.5°C |
| 太阳表面 | 5,778 K | 5,504.85°C |
| 太阳核心 | 1.57×10⁷ K | 1.57×10⁷ °C* |
| 托卡马克等离子体(ITER 目标) | 1.5×10⁸ K | 约 1.5×10⁸ °C* |
*在这种量级上,273.15 K 的偏移量只是舍入噪声,摄氏和开尔文的读数实际上已经相同。
常见问题
摄氏转华氏的公式是什么?
把摄氏乘以 9/5(或 1.8),再加 32:°F = °C × 9/5 + 32。例如 25°C × 1.8 + 32 = 77°F。乘数反映的是两种温标在冰点到沸点之间跨度的 180:100 比值,加上的 32 是为了对齐它们不同的零点。
华氏转摄氏的公式是什么?
先把华氏值减去 32,再乘以 5/9:°C = (°F − 32) × 5/9。对 72°F 来说,就是 (72 − 32) × 5/9 = 40 × 5/9 ≈ 22.22°C。先减后乘,顺序反了会得到错误答案。
摄氏和华氏在什么温度下相等?
恰好在 −40 度。把 °C = °F 代入换算公式得到 °C = °C × 9/5 + 32,解出 °C = −40。这是两种温标读数相同的唯一一个温度,对现实的极寒天气和换算方向 bug 都是一个实用的校验锚点。
烘焙时 350°F 换成摄氏是多少?
350°F 约等于 176.67°C。欧洲食谱通常把它取整到 180°C,不少美制转公制的对照表写 175°C。在家用烤箱里两个值都能用,那个量级的温度稳定性比这点舍入误差还差。需要精确值的场景请用我们的温度换算工具。
100°F 换成摄氏是多少?
100°F ≈ 37.78°C。这稍高于正常体温(37°C / 98.6°F),常被视作轻度发热的起点。医学指南通常把 38°C / 100.4°F 作为真正意义上的发热阈值,所以 100°F 属于临界值,但还未达到临床显著。
为什么绝对零度是 −273.15°C 而不是 −273?
因为 2019 年 SI 重定义精确固定了玻尔兹曼常数,使 −273.15°C 成为绝对零度的精确计算值,而不再是一个取整的近似。2019 年之前,摄氏零点与水的三相点挂钩,0.15 这一段来自测量。现在它按定义就是精确值。
代码里什么时候该用开尔文而不是摄氏?
只要涉及温度的乘、除或乘方运算(黑体辐射 T⁴、理想气体计算、反应速率),都该用开尔文。开尔文不会变负,除法始终稳定。计算温度差时,摄氏和开尔文可以互换(5 度的变化在两者中是一样的)。
2026 年还有人用兰氏吗?
用,但很窄。美国的机械工程、HVAC 和航空航天领域仍然在热力学循环分析里使用兰氏,前提是其他所有输入都是华氏。在这些领域之外、以及美国之外,它基本已经消亡。如果你在写通用软件,支持兰氏是一份便宜的保险,但很少真正起作用。
SQL 查询里怎么做温度换算?
内联公式,或者用 GENERATED ALWAYS AS 生成列。例如:SELECT celsius * 9.0 / 5.0 + 32.0 AS fahrenheit FROM readings。这里写 9.0 和 5.0(而不是 9 和 5)是为了在大多数数据库里强制走浮点运算;整数除法会静默截断。加一条 CHECK (celsius >= -273.15),在插入时就拦住非法值。
心算摄氏转华氏最简单的方式是什么?
把摄氏值翻倍再加 30。22°C × 2 + 30 = 74°F(实际 71.6°F)。在 0–30°C 范围内精度在 2°F 左右,已经覆盖了几乎所有天气和室内温度。反向走:华氏减 30 再折半。
为什么我的温度换算器对 37°C 返回 98.599999?
因为 9/5 = 1.8 在二进制浮点里无法精确表示,于是 37 × 9 / 5 + 32 算出的是 98.60000000000001,而不是 98.6。这是 IEEE 754 的正常行为,不是 bug。展示时用 toFixed(2);如果你的业务对末尾几位精度敏感,就换用十进制库。
可以把温度存成整数来规避浮点问题吗?
可以。存储十分之一摄氏度(摄氏值乘以 10)。37.0°C 存成 370,22.5°C 存成 225。整数运算是精确的,只在显示边界除以 10。这种模式在嵌入式系统和高吞吐时序数据库中很常见,那里每一字节磁盘和每一个 CPU 周期都要计较。
API 响应里出现了没有单位的数字怎么处理?
绝不要这样设计。每一个温度字段都应该显式携带单位:要么把单位放进字段名(temp_celsius、temp_k),要么在旁边加一个 unit 字段。如果你是 API 的消费方而对方没提供,就在代码里把这个假设大声写明,再补一条契约测试:一旦 API 默认值变了就立刻失败。
水的沸点在四种温标下分别是多少?
100°C = 212°F = 373.15 K = 671.67°R,前提是标准大气压(1 atm,101.325 kPa)。气压很重要:在丹佛的海拔,水在大约 95°C 就开始沸腾;到了珠峰山顶,降到约 71°C。沸点是随气压变化的量,不是宇宙常数。
温度值在浮点运算里会比其他数字更特殊吗?
不会。温度数值的表现和任何其他浮点数一样。实际上要小心的是,换算公式里的 5/9 和 9/5 因子会在每一步换算中引入舍入误差。对 200–400 区间的开尔文值来说精度完全够用;对接近可表示双精度边界的负摄氏值来说也还好。真正的坑是串联换算导致误差累积:做一次换算,存好其中一种规范形式。