Swift里的数值变量的最大值和最小值

Swift里有很多种数值变量,如Int,Int8,Float,Double等。和绝大多数编程语言一样,由于是在计算机上运行,内存有限,所以必有最大值和最小值,而计算机无法处理超过该值的数。

在Swift中,数字变量类型都有一些静态属性,其固定值为该类变量的最大值和最小值。

一、整数型变量

(一)如何找到最大值和最小值

Swift里的整数型变量有Int,Int8,Int16,UInt等。这一类的变量,都可通过max,min来找到该类变量的最大值和最小值[1]

Swift 复制代码
print("Part 1: Integer bounds:\n")
var maxInt = Int.max //2^63-1
var minInt = Int.min //-2^63
print("The max Int is \(maxInt), and the min Int is \(minInt)")
var maxUInt = UInt.max //2^64-1
var minUInt = UInt.min //0
print("The max UInt is \(maxUInt), and the min UInt is \(minUInt)")
var maxInt8 = Int8.max
var minInt8 = Int8.min 
print("The max Int8 is \(maxInt8), and the min Int8 is \(minInt8)")

对于有符号整数类型,Int占64字节,Int32占32字节,以此类推。若该变量占字节数为,则其最大值为,最小值为。对于无符号整数类型,UInt,UInt32等占字节数和有符号类型类似,但最大值为,最小值为。所以上述代码的运行输出为:

(二)超出最大值或最小值的溢出情况

我们知道,在C++中,如果出现了溢出现象,不会报错,而是会跳转至另一端。例如,对于int类型变量,最大值是2147483647,最大值+1就会计算出最小值-2147483648[2]

cpp 复制代码
#include <iostream> 
#include <string>
#include <climits>
using namespace std;
void main(){
    int num = INT_MAX;
    int too_big_num = num + 1;
    cout << "num=" << num << '\n';
    cout << "too_big_num=" << too_big_num;
}

上述代码运行输出为

那么在Swift中呢?

Swift 复制代码
import Foundation

var num = Int.max
var too_big_num = num + 1
print("num=\(num)")
print("too_big_num=\(too_big_num)")

该程序运行会报错

这个错误是溢出错误。Swift不像C++,在处理整型变量时并不会在溢出时跳转到另一端。

那么,能不能用try ... catch的语句捕捉这个错误呢?

Swift 复制代码
import Foundation

var num = Int.max
var too_big_num:Int?
do{
    too_big_num = try?(num + 1)
}
catch{
    print("Overflow")
}
print("num=\(num)")
print("too_big_num=\(too_big_num)")

该代码仍然无法运行,会报错。

原因在于,这样的溢出错误在Swift中属于FatalError。Swift的try ... catch机制无法处理FatalError[3]。有关Swift的错误捕获机制,请阅读[3]

二、小数型变量

在Swift中,对于小数型变量,也就是Float和Double类型,不能像整型变量那样用max和min来得到最大值和最小值。但对于这一类变量,Swift里也定义了一些静态属性,表明它们的极限值[4]

(一)小数型变量的极限值

小数型变量和整数型变量的区别在于小数型变量,即实数,从纯数学角度来看是连续的,也就是两个不同的实数中间总存在第三个实数[5],即不存在相邻的两个实数。因此,数学上不存在最接近0的非零实数,但作为计算机编程语言,Swift不可能处理"无限接近"的概念。因此小数型变量的极限值有以下三种[4]

(1)greatestFiniteMagnitude:Swift能处理的最大的绝对值,超过该值即为溢出。

(2)leastNormalMagnitude:Swift能处理的最小的正常态数,若小于该数,则Swift处理时无法保证精度。

(3)leastNonzeroMagnitude:Swift能处理的最小正数,也就是Swift能处理的不为零的绝对值最小值。

关于常态数(normal value)和非常态数(subnormal value)的区别,详见[6]。更具体的解释在[7]。简单地说,因为小数在计算机里表达的形式是,其中是一个用指定个数的bit表示的2进制小数(Float类型24位,Double类型53位),且规定只有第一位在小数点前;是一个二进制表示的整数,Float类是-126~+128之间(8位),Double类是-1022~+1024之间(11位))。[7]中说Double类的指数最小-2046似乎不对,但也可能是Swift和别的语言不完全一样。而最小的正常态数是指首位为1的数中最小的数(此时已取最小值-126,而更小的数称为非常态数,所以计算精度会减小,因为首位不为1所以尾数(mantissa)的有效位数(significant bit)减少了[6]

(二)比最大值更大或比最小值更小的溢出情况

在Swift中,对于小数型变量,即使溢出,也不会报错,而是会给出一个预留的特殊值。

如果绝对值超过最大值,则计为"无穷大"。如果绝对值小于最小值,则计为0。

Swift 复制代码
print("\nPart 2: Floats and Doubles\n")
//But to get the greatest finite Float/Double, use this
var maxFloat = Float.greatestFiniteMagnitude
print("The max finite Float is \(maxFloat)")
var tooBigFloat = maxFloat * 1.1 //too big then infinity
print("If the Float is too big, then it becomes \(tooBigFloat)")
var tooBigFloat2 = Float.infinity //you can create infinity by a Swift function
print("Infinity can be created with Float.infinity. tooBigFloat2 = \(tooBigFloat2)")
var undef = tooBigFloat * 0 // 0*inf is undefined
print("0*inf is \(undef)")
var undef2 = Float.nan //you can create nan by a Swift function
// in addition, you can also find the smallest magnitude, which means that anything with absolute number smaller than this will be regarded as 0
var minFloat = Float.leastNonzeroMagnitude
print("The min non-zero Float is \(minFloat)")
var tooSmallFloat = minFloat / 2
print("If the Float is too small, then it becomes \(tooSmallFloat)")

运行输出为:

注意:Swift中对于Float和Double,存在inf(无穷大)和nan(未定义)。

(三)小于最小的常态数但不为0

正如前面说到的,非常态数的精度不如常态数。

下面的例子里,定义一个最小常态数minNormalDouble,再定义一个最小的非0数minDouble(小于minNormalDouble),然后把它们分别乘以1.01,观察结果是否能被判断出比原来大。

Swift 复制代码
var maxDouble = Double.greatestFiniteMagnitude
print("The max finite Double is \(maxDouble)")
var minDouble = Double.leastNonzeroMagnitude
print("The least non-zero Double is \(minDouble)")
var minNormalDouble = Double.leastNormalMagnitude
print("The least normal Double is \(minNormalDouble)")

//How normal magnitude is different from non-zero magnitude?
print("\nPart 2.5: difference between normal and non-zero\n")
print("minDouble * 1.01 > minDouble? \(minDouble * 1.01 > minDouble)")

print("minNormalDouble * 1.01 > minNormalDouble? \(minNormalDouble * 1.01 > minNormalDouble)")

运行输出为:

从结果中可看出,最小常态数minNormalDouble在乘以1.01后,大于原值,但最小非零数minDouble在乘以1.01后,并不大于原值。这是因为最小非零数minDouble的精度不足以计算它的0.01倍的差别,不如最小常态数minNormalDouble的精度。

三、总结

对于Swift里的数值类型的变量,可以通过其类的自带静态属性找出最小值和最大值。其中,对于整数型变量,一旦越过最值,就会报错;但对于小数型变量,即使越过最值也不会报错,而是会用特殊的方法计算。另外,常态数和非常态数的区别在于精度。

四、参考资料

1\][Swift学习笔记(九)------整型Int在Swift中表示的最大值最小值问题_swift int 最大值-CSDN博客](https://blog.csdn.net/chenyufeng1991/article/details/47070913 "Swift学习笔记(九)——整型Int在Swift中表示的最大值最小值问题_swift int 最大值-CSDN博客") \[2\][【C++】详解 INT_MAX 和 INT_MIN(INT_MAX 和 INT_MIN是什么?它们的用途是什么?如何防止溢出?)_c++ int max-CSDN博客](https://blog.csdn.net/weixin_45031801/article/details/136877709 "【C++】详解 INT_MAX 和 INT_MIN(INT_MAX 和 INT_MIN是什么?它们的用途是什么?如何防止溢出?)_c++ int max-CSDN博客") \[3\][Swift --- 错误处理(Error):throws、断言assert、fatalError_fatalerror swift-CSDN博客](https://blog.csdn.net/songzhuo1991/article/details/100776550 "Swift --- 错误处理(Error):throws、断言assert、fatalError_fatalerror swift-CSDN博客") \[4\][Swift中Double的常见一些API - 简书](https://www.jianshu.com/p/808b842eaed1 "Swift中Double的常见一些API - 简书") \[5\][如何理解实数的连续性?](https://www.zhihu.com/question/282831758 "如何理解实数的连续性?") \[6\][Normal vs Subnormal Floats \| Programming.Guide](https://programming.guide/normal-vs-subnormal-floats.html "Normal vs Subnormal Floats | Programming.Guide") \[7\][15张图带你深入理解浮点数](https://www.cnblogs.com/hzy1987/p/18021627 "15张图带你深入理解浮点数")

相关推荐
文件夹__iOS1 小时前
深入浅出 iOS 对象模型:isa 指针 与 Swift Metadata
ios·swift
I烟雨云渊T1 天前
iOS实名认证模块的具体实现过程(swift)
ios·cocoa·swift
Swift社区2 天前
LeetCode 270:在二叉搜索树中寻找最接近的值(Swift 实战解析)
算法·leetcode·swift
I烟雨云渊T2 天前
iOS瀑布流布局的实现(swift)
开发语言·ios·swift
Pythonliu74 天前
启智平台调试 qwen3 4b ms-swift
开发语言·swift
画个大饼5 天前
iOS启动优化:从原理到实践
macos·ios·objective-c·swift·启动优化
画个大饼13 天前
Swift中Class和Struct的深度对比分析
开发语言·ios·swift
桃花仙丶14 天前
iOS/Flutter混合开发之PlatformView配置与使用
flutter·ios·xcode·swift·dart
一牛14 天前
译:Swift中的隔离机制介绍
macos·ios·swift
hepherd14 天前
iOS - 音频: Core Audio - 播放
swift·音视频开发