摘要

知其然,更要知其所以然。前段时间用 String 转换 Int 处理时,发现一种情况返回 nil,就换成 String 转换 Double 的方式处理。今天就要来看看这种返回 nil 的情况是怎么造成的。

当有小数的 String 文本转换为 Int 类型时,返回的值并不是咱们想要的向下取整后的整数,而是 nil。

// Int 转换为 String
let intStr = "2.78"
let int = Int(intStr) // nil

为什么是nil?今天就来解解这个疑惑。

String 转换 Int 本质

首先com+鼠标左键弹出选项,选择jump to Definition(跳转到定义)一波操作,来到 Int 的定义地方,直接全局搜索一下 String,直接看下定义。

    /// Creates a new integer value from the given string.
///
/// The string passed as `description` may begin with a plus or minus sign
/// character (`+` or `-`), followed by one or more numeric digits (`0-9`).
///
/// let x = Int("123")
/// // x == 123
///
/// If `description` is in an invalid format, or if the value it denotes in
/// base 10 is not representable, the result is `nil`. For example, the
/// following conversions result in `nil`:
///
/// Int(" 100") // Includes whitespace
/// Int("21-50") // Invalid format
/// Int("ff6600") // Characters out of bounds
/// Int("10000000000000000000000000") // Out of range
///
/// - Parameter description: The ASCII representation of a number.
@inlinable public init?(_ description: String)

出处找到了,不想费力看注释的,直接看我给的结论:

String 转换为 Int 类型,传入 Int 的 description 参数,必须是一个或者多个0-9组合的整数,整数前可以加“+”或者“-”。通俗说,这个 text 文本必须是一个整数。否则都返回 nil。

看到现在,大致可以明白了Int("2.78")为什么是 nil。

String 转换 Double 本质

看完String 转换 Double 本质后,顺势也看下String 转换 Double 本质。同样的查找逻辑一波操作,找到它的定义

extension Double : LosslessStringConvertible {

    /// Creates a new instance from the given string.
///
/// The string passed as `text` can represent a real number in decimal or
/// hexadecimal format or special floating-point values for infinity and NaN
/// ("not a number").
///
/// The given string may begin with a plus or minus sign character (`+` or
/// `-`). The allowed formats for each of these representations is then as
/// follows:
///
/// - A *decimal value* contains the significand, a sequence of decimal
/// digits that may include a decimal point.
///
/// let c = Double("-1.0")
/// // c == -1.0
///
/// let d = Double("28.375")
/// // d == 28.375
///
/// 此处省略 57 行注释------------------
///
/// - Parameter text: The input string to convert to a `Double` instance. If
/// `text` has invalid characters or is in an invalid format, the result
/// is `nil`.
@inlinable public init?<S>(_ text: S) where S : StringProtocol @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
public init?(_ text: Substring)
}

Double(string)中的 string 文本可以是一个10进制、16进制或者浮点数的(这个非常关键)。也可以添加“+”,“-”符号。

这里简单总结一下,Double 转换为 text,并保留几位小数的处理方法,加深一些印象

let double = Double(2.7895)
// double 转换为 String
print("\(double)") // 输出 "2.7895" // 保留两位小数
print(String(format:"%.2f", double) // 输出 "2.79"

Int("2.78") 怎么处理,不是 nil?

看完了上面两个转换的定义之后,那么是否可以组合一下,解决可能出现的 nil?那是当然。

首先将文本转换为 Double,然后将 Double 转换为 Int

Int(Double("2.78")!) // 2

Double 转换 Int

代码验证没有问题,那么就看看,Double 转换 Int 做了什么事情。


/// Creates an integer from the given floating-point value, rounding toward
/// zero.
///
/// Any fractional part of the value passed as `source` is removed, rounding
/// the value toward zero.
///
/// let x = Int(21.5)
/// // x == 21
/// let y = Int(-21.5)
/// // y == -21
///
/// - Parameter source: A floating-point value to convert to an integer.
/// `source` must be representable in this type after rounding toward
/// zero.
public init(_ source: Double)

定义中可以看到,Double 类型的数据,经过 Int 转换后,会生成一个只保留整数的数(小数部分略去)。所以也就支持了上节部分的处理方式。

Double 类型整数省略 .000

在看 Double 转换 Int定义时,无意间发现一个好玩的定义,先上定义


/// Creates an integer from the given floating-point value, if it can be
/// represented exactly.
///
/// If the value passed as `source` is not representable exactly, the result
/// is `nil`. In the following example, the constant `x` is successfully
/// created from a value of `21.0`, while the attempt to initialize the
/// constant `y` from `21.5` fails:
///
/// let x = Int(exactly: 21.0)
/// // x == Optional(21)
/// let y = Int(exactly: 21.5)
/// // y == nil
///
/// - Parameter source: A floating-point value to convert to an integer.
public init?(exactly source: Double)

定义说明,可以将一个精确标示的浮点数转换为 Int 类型。这里的精确标示就是没有小数的值。有了这个定义,那么岂不是可以解决某一个应用场景了吗?

显示存在需要保留2位小数的文本时,当浮点数是一个没有小数的数值,那么就显示整数。

// old
String(format: "%.2f", 2.578) // 2.58
String(format: "%.2f", 2.0) // 2.00 // new
if Int(exactly: 2.00) != nil {
"\(Int(exactly: 2.00)!)" // 2
}

题外话

感谢看到这里,感觉有一点收获,给个小赞。有分析的不到位,评论区留言帮我梳理。

偶尔有一些想要搞清楚的问题,评论区告诉我,咱们一起解决。

Swift-为什么String转换Int的结果是nil的更多相关文章

  1. swift 中String,Int 等类型使用注意,整理中

    swfit中的String和Int是 struct定义的,不同于NSString和NSNumber, 如果想在一个数组中同时包含String和Int,那么这个数组要声明为[Any] 而不是 [AnyO ...

  2. java 13-4 Integer和String、int之间的转换,进制转换

    1.int类型和String类型的相互转换 A.int -- String 推荐用: public static String valueOf(int i) 返回 int 参数的字符串表示形式. B. ...

  3. (二)javascript中int和string转换

    在javascript里怎么样才能把int型转换成string型 (1)var x=100 a = x.toString() (2)var x=100; a = x +""; // ...

  4. C# 中怎么将string转换成int型

    int intA = 0;1.intA =int.Parse(str);2.int.TryParse(str, out intA);3.intA = Convert.ToInt32(str);以上都可 ...

  5. C++有没有string转化int的函数,怎样转换

    有两种方法1. c++中string到int的转换 1) 在C标准库里面,使用atoi: #include <cstdlib>#include <string> std::st ...

  6. Go语言string,int,int64 ,float转换

    (1)int转string s := strconv.Itoa(i)等价于s := strconv.FormatInt(int64(i), 10) (2)int64转string i := int64 ...

  7. go语言学习--string、int、int64互相转换,字符串的截取,数组和字符串的转换

    下面总结了go中常用的转换 #string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt ...

  8. golang学习笔记13 Golang 类型转换整理 go语言string、int、int64、float64、complex 互相转换

    golang学习笔记13 Golang 类型转换整理 go语言string.int.int64.float64.complex 互相转换 #string到intint,err:=strconv.Ato ...

  9. Android-Kotlin-函数表达式&String与Int转换$异常处理

    Kotlin的函数表达式: package cn.kotlin.kotlin_base03 /** * 函数第一种写法 */ fun addMethod1(number1: Int, number2: ...

随机推荐

  1. 扩展LLVM:添加指令、内部函数、类型等

    扩展LLVM:添加指令.内部函数.类型等 Introduction and Warning Adding a new intrinsic function Adding a new instructi ...

  2. node和gulp版本的坑

    现在node版本最新的稳定版在14+ 然后我在接手项目的时候使用gulp打包,怎么也打包不了,这个问题纠结了挺久,然后百度了下,发现版本的问题 node 12+ 以上的版本不兼容 gulp 3的版本 ...

  3. 【Azure 应用服务】Azure Web App的服务(基于Windows 操作系统部署)在被安全漏洞扫描时发现了TCP timestamps漏洞

    问题背景 什么是TCP timestamps(TCP 时间戳)? The remote host implements TCP Timestamps, as defined by RFC1323 (h ...

  4. 汉枫Wi-Fi串口服务器HF2211S应用案例

    实现的功能 该模块上电后主动以mobusRTU协议,通过本模块的串口将气体检测仪的4路传感器数据读取 模块上电后连接指定WiFi,通过MQTT协议将读取到的数据以JSON格式推送到指定服务器. 具体细 ...

  5. kerberos安装配置

    目录 前言 服务端安装 组件安装 配置krb5.conf 配置kdc.conf 配置kadm5.acl 创建kdc数据库 在server端创建一个管理员账号,方便远程登录管理kerberos 正式启动 ...

  6. Spring Boot 异步请求和异步调用,一文搞定

    一.Spring Boot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如 ...

  7. Java @SuppressWarnings:抑制编译器警告-4

    Java 中的 @SuppressWarnings 注解指示被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告,且会一直作用于该程序元素的所有子元素.例如,使用 @Supp ...

  8. 关于Linux服务器部署

    服务器信息: 此小节的内容: SecurityCRT:用来连接到Linux服务器命令操作. FTP(FTPRush):本地文件和Linux服务器文件交互的 工具服务器 借助客户端工具来链接到Linux ...

  9. Pytest学习笔记4-assert断言

    前言 pytest作为单元测试框架,自然少不了断言功能,用过unittest的人都知道,在unittest中有丰富的断言方法,比如assertEqual().assertIn().assertTrue ...

  10. 使用echarts时,鼠标首次移入屏幕会闪动,全屏会出现滚动条

    原因: 在echarts图表中出现tooltip时,画布的父标签(即:echarts.init()的标签)的有时宽高都会发生变化,导致相对布局的div可能大小发生变化(画布大小却不变),导致页面闪动. ...