F#奇妙游(8):计量单位
F#的计量单位
从各个意义上,都可以说计量单位很重要。度量衡的统一是社会化大生产和市场交换的基石。这句正确的废话跟F#没有半毛钱的关系,直到我看帮助看到了这个:
[<Measure>] type m
let l = 1<m>
脑袋顿时秃起来哦不兴奋起来。仔细看了看几个帖子,发现这个东西是F#的一个特性,叫做Units of Measure。
其实网上提的不太多,本来F#的内容就少。
- 比较高访问量的:F# Units of Measure
- Wikibooks上的:F Sharp/Units of Measure
- 一个停更很久的小伙子“要你命3000”:BrendoTRON3000’s Programming Blog有两个帖子。
为什么需要这个计量单位
这个特性看起来很美好,编程序的时候能够把单位写在变量的后面,可以自动检查单位的正确性,比如:
// open FSharp.Data.UnitSystems.SI.UnitSymbols
// 或者自己定义下:
[<Measure>] type m
[<Measure>] type s
let speed = 10<m/s>
let time = 5<s>
let distance = speed * time
这里距离自动推导出距离的单位m
,而且speed * time
的结果也是m
,如果写成speed + time
就会报错,因为单位不匹配。
好多帖子里面还提到NASA把单位搞错,导致火箭坠毁,这个我没仔细去找相关的资料。不过老美那个没文化的,全球都在搞国际单位制,就他抱着英制不放,看NACA(NASA早期的名字)的文章简直是费了劲。
只是这个单位写法和用法,都是编译期的,在运行期间,这个单位就没有了。没有办法访问,没有办法转字符串,没有办法获取和判断。唯一的用处就是在编译时候检查单位的正确性。
这么好的奇淫巧技,微软到底是怎么让它进入F#的呢?我思考了非常久,也没有想明白。因为这个东西这么好的话,C/C++/Java肯定早就要搞起来了啊?为什么呢?
为什么C/C++/Java没有这个计量单位的功能
我想了很久,也没有想明白。我觉得可能是因为这个东西太复杂了,而且用处不大。比如我写了一个函数:
let f (x:float) = x + 1.0
这个函数的输入是float
,输出也是float
,那么我在调用的时候,就不需要写f 1.0f
,因为编译器会自动推导出来。如果我写成:
let f (x:float<m>) = x + 1.0<m>
有两种可能:
- 通过命名约定、检查工具、单元测试,不管是什么东西,在别的主流工程语言中,这个问题不复存在。所以这个功能就没有必要了。
- 这个功能实现起来跟人类实现度量衡统一一样难,最聪明的物理学家,到现在连功的单位都没有统一,简直是人类之耻。
- F#做这个功能实在是太简单?所以语言实现的胸弟随便就做上了?
为了开心和不开心,我还是把跟这个相关的东西都看了一遍,头发少了好几根。
真正有用的Unit of Measure
说这个玩意没有用是一方面,说计量单位没有用那就是胡扯。有一个很好的包叫做CoolProp
,可以计算各种物质的物理性质,比如下面的代码输入是温度和压力,输出是密度。这个密度的单位是kg/m^3
。
let water = CoolProp.PropsSI("D","T",300.0,"P",101325.0,"Water")
这个包C++编的,提供了.NET接口,叫做SharpProp,用F#可以直接调用。
let water = SharpProp.PropsSI("D","T",300.0,"P",101325.0,"Water")
这么下起来是不是很没有牌面?
.NET程序员(准确地说是C#程序员)大神,做了一个很有用的单位系统。这个东西叫做UnitsNet。这个东西是用C#写的,但是F#也可以直接调用。
open System
open SharpProp
open UnitsNet.Units
open UnitsNet.NumberExtensions.NumberToPressure
open UnitsNet.NumberExtensions.NumberToTemperature
open UnitsNetlet fluid (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins()))type Fluid withmember this.density = this.Density.KilogramsPerCubicMetermember this.pressure = this.Pressure.Pascalsmember this.temperature = this.Temperature.Kelvinsmember this.specificHeat = this.SpecificHeat.JoulesPerKilogramKelvinmember this.viscosity =match this.DynamicViscosity with| v when v.HasValue -> v.Value.NewtonSecondsPerMeterSquared| _ -> Double.NaNmember this.kinematicViscosity =match this.KinematicViscosity with| v when v.HasValue -> v.Value.SquareMetersPerSecond| _ -> Double.NaNlet density (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).Density.KilogramsPerCubicMeterlet specificHeat (f: FluidsList) (p: float) (T: float) =(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).SpecificHeat.JoulesPerKilogramKelvinlet viscosity (f: FluidsList) (p: float) (T: float) =match(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).DynamicViscositywith| v when v.HasValue -> v.Value.NewtonSecondsPerMeterSquared| _ -> Double.NaNlet kinematicViscosity (f: FluidsList) (p: float) (T: float) =match(new Fluid(f)).WithState(Input.Pressure(p.Pascals()), Input.Temperature(T.Kelvins())).KinematicViscositywith| v when v.HasValue -> v.Value.SquareMetersPerSecond| _ -> Double.NaN[<EntryPoint>]
let main argv =for T in 280..10..350 dolet water = fluid FluidsList.Water 101325.0 (float T)printfn$"%20f{water.density} kg/m³%20f{water.pressure} Pa%20f{water.temperature} K%20e{water.viscosity} Pa·s%20e{water.kinematicViscosity} m²/s%20f{water.specificHeat} J/kg·K"printfn ""for T in 280..10..500 dolet air = fluid FluidsList.Air 101325.0 (float T)printfn$"%20f{air.density} kg/m³%20f{air.pressure} Pa%20f{air.temperature} K%20e{air.viscosity} Pa·s%20e{air.kinematicViscosity} m²/s%20f{air.specificHeat} J/kg·K"0 // return an integer exit code
很简单的就能把各个单位在运行期的行为都统一起来。这个东西是真正有用的。
UnitsNet的功能举例
UnitsNet把一个带单位的量描述为(数值,单位)的组合,不同的单位之间的转换都在运行时可以获得,各单位的名称也都是在运行时可以获得的。这个东西的功能非常强大,可以用来做各种单位转换,比如下面的代码就是把压力从帕斯卡转换为其他单位。
open UnitsNet
open UnitsNet.Units
open UnitsNet.NumberExtensions.NumberToPressure
// 用不同的单位定义一个量
let p = 101325.0.Pascals()
let p1 = 1.0.Atmospheres()
let p2 = 760.0.Torr()
let p3 = 14.695948775513.PoundsForcePerSquareInch()
let p4 = 1013.25.Millibars()
let p5 = 1013.25.Hectopascals()
// 把一个量转化为不同的单位
printfn $"%f" p.Atmospheres
printfn $"%f" p.Torr
printfn $"%f" p.PoundsForcePerSquareInch
总结
- F#的Unit of Measure是一个很有意思的功能,但是实际上没有什么用。
- UnitsNet实现的单位系统是真正有用的。
- F#调用C#的库还是很好很强大的。
F#奇妙游(8):计量单位相关推荐
- F#奇妙游(6):如何不用for循环以及循环
For循环 在F#中,for循环的语法如下: for <identifier> = <start> to <end> do<body> 但是所有函数式编 ...
- F#中有趣的计量单位
"失足"的NASA气象卫星 1998年2月,美国宇航局(NASA)发射了一枚探测火星气象的卫星,预定于1999年9月23日抵达火星.然而研究人员惊讶地发现,卫星没有进入预定的轨道, ...
- 阿里文娱旗下优酷联合河南卫视推出2022“元宵奇妙游”,创新传承传统文化
随着中国经济的发展,中华民族越来越自信,国潮风愈演愈烈,中华文化带有典型的中国特色,如今国潮已经悄悄席卷各大行业,中国元素已经成为人们追逐的对象.文化产业亦是如此,河南卫视宣扬民族文化,在各大卫视中脱 ...
- INTRODUCING F#
第一篇,从零开始编写我们的第一个F#程序. 什么是F#,我为何要学它? F#是一种.NET平台上的函数式编程语言.就像C#和VB.NET,F#可以利用.NET的核心类库,如WPF,WCF,VSTO等等 ...
- 95后热搜哪些事,夸克用AI引擎发布2021年度关键词
编辑 | 宋慧 出品 | CSDN 云计算 岁末将至,哪些心潮澎湃的瞬间与难以忘怀的言语,能够代表你的2021? 12月14日,在夸克''Meet AI''开放日上,阿里巴巴智能信息事业群旗下的智能搜 ...
- 坚定文化新自信 提升文化软实力
<坚定文化新自信 提升文化软实力> 党的十九大报告指出,文化是一个国家.一个民族的灵魂.文化兴国运兴,文化强民族强.文化是人类文明的精华,是时代发展的荟萃,是社会创造力的源泉,是国际地位软 ...
- 迪士尼超级计算机多少钱,上海迪士尼乐园公布票务调整方案,明年1月9日起实行新票价...
原标题:上海迪士尼乐园公布票务调整方案,明年1月9日起实行新票价 上海迪士尼度假区今天公布票务调整方案,新方案将于2022年1月9日起实行.届时,上海迪士尼度假区将在现行四级票价结构下调整门票价格,各 ...
- 阿里大文娱让中国传统文化融入年轻人的生活
2021年10月,阿里大文娱旗下优酷和河南广电达成战略合作,双方合作,推出了多台中国风晚会. 早在2020年,阿里大文娱联合阿里创新事业群,推出了青年文娱消费大数据报告,这份报告显示,中国的流行音乐相 ...
- Python 之 小白爬虫
设置环境 import requests from lxml import etree #lxml解析库的etree方法 爬取微博热搜榜 url = 'https://s.weibo.com/top/ ...
最新文章
- nginx配置http、https访问,nginx指定ssl证书,阿里云腾讯云华为云设置nginx https安全访问
- springboot 自动装配_Spring Boot 自动装配流程
- MySQL最高每秒57万写入,带你装X,带你飞!
- 推荐六款帮助你实现惊艳视差滚动效果的 jQuery 插件
- SQL Server timeout分析和总结
- 程序员如何在百忙中更有效地利用时间,如何不走岔路,不白忙(忙得要有效率,要有收获)...
- [Asp.net MVC]HandleErrorAttribute异常过滤器
- quicksearch连接oracle,dos命令下连接oracle数据库表
- Python设计模式:建造者模式
- 网易云音乐数仓建模实践
- 自我成长与团队管理——一些总结
- c++语言生成一个随机数,C++ 快速随机数生成器
- Fiddler+手机模拟器+java采集抖音评论数据
- iOS-打开本地或下载的Excel文件
- Android熄屏与亮屏控制
- TK 设置tkinter窗口的置顶属性,保持最上层
- Win11新加硬盘不显示的解决方法
- 亲爱的老狼-display的应用
- windows10使用cuda11搭建pytorch深度学习框架——运行Dlinknet提取道路(二)——代码运行问题解决
- 阿里云开发者大会正式启动