摘要

知其然,更要知其所以然。前段时间用 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. CodeGen按钮循环

    CodeGen按钮循环 按钮循环是一个模板文件构造,它允许您迭代CodeGen拥有的按钮信息集合.              在按钮循环中处理的按钮的定义可以来自两个位置之一. 如果基于UI工具箱输入 ...

  2. 重新整理 .net core 实践篇—————静态中间件[二十一]

    前言 简单整理一下静态中间件. 正文 我们使用静态文件调用: app.UseStaticFiles(); 那么这个默认会将我们根目录下的wwwroot作为静态目录. 这个就比较值得注意的,可能刚开始学 ...

  3. 使用 Docker 部署 Node 应用 - 镜像文件尺寸的优化

    前面 使用 Docker 部署 Node 应用 一文中完成了镜像的创建和运行,不过生成的镜像还有些粗糙,需要进一步优化. 镜像的优化 通过 docker images 看到简单的一个 node 服务端 ...

  4. 一起来踩踩 Spring 中这个循环依赖的坑

    1. 前言 2. 典型场景 3. 什么是依赖 4. 什么是依赖调解 5. 为什么要依赖注入 6. Spring的依赖注入模型 7. 非典型问题 参考资料 1. 前言 这两天工作遇到了一个挺有意思的Sp ...

  5. Springboot自定义starter打印sql及其执行时间

    前面写到了通过实现mybatis提供的org.apache.ibatis.plugin.Interceptor接口实现了打印SQL执行时间,并格式化SQL及其参数,如果我们使用的是ssm还得再配置文件 ...

  6. 题解 P1850 [NOIP2016 提高组] 换教室

    做完这道题才略微感觉自己懂了一点关于概率与期望的知识QAQ... 一:关于概率与期望的定义 转载节选于blog 1.什么是数学期望? 数学期望亦称期望.期望值等.在概率论和统计学中,一个离散型随机变量 ...

  7. 动态路由协议与RIP配置

    一.动态路由的概述 二.RIP路由协议工作原理 三.水平分割 四.RIP路由协议v1与v2的区别 五.实验配置 一.动态路由的概述 1.定义 动态路由是指利用路由器上运行的动态路由协议定期和其他路由器 ...

  8. external-provisioner源码分析(2)-main方法与Leader选举分析

    更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 external-provisioner源码分析(2)-main方法与Leader选举分析 本 ...

  9. jQuery获取标签信息

    <!DOCTYPE html><html><head>    <meta charset="utf-8"/>    <titl ...

  10. python读取csv文件数据绘制图像,例子绘制天气每天最高最低气温气象图