摘要

知其然,更要知其所以然。前段时间用 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. 使用Relay部署编译ONNX模型

    使用Relay部署编译ONNX模型 本文介绍如何使用Relay部署ONNX模型的入门. 首先,必须安装ONNX软件包. 一个快速的解决方案是安装protobuf编译器,然后 pip install o ...

  2. 循环IRNNv2Layer实现

    循环IRNNv2Layer实现 IRNNv2Layer实现循环层,例如循环神经网络(RNN),门控循环单元(GRU)和长期短期记忆(LSTM).支持的类型为RNN,GRU和LSTM.它执行循环操作,该 ...

  3. ARM Cortex-M嵌入式C基础编程(下)

    ARM Cortex-M嵌入式C基础编程(下) ARM Cortex-M Embedded C Fundamentals/Tutorial -Aviral Mittal Load Region Vs ...

  4. 24GHz和77GHz毫米波雷达技术细节

    24GHz和77GHz毫米波雷达技术细节 FMCW Radar Sensitivity Measurement Tech Field Test and Raw Data Analysis Capabi ...

  5. 算法训练 区间k大数查询(题解)

    资源限制 时间限制:1.0s   内存限制:256.0MB   问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个.   输入格式 第一行包含一个数n,表示序列长度. 第二行包 ...

  6. JavaScript 中精度问题以及解决方案

    JavaScript 中的数字按照 IEEE 754 的标准,使用 64 位双精度浮点型来表示.其中符号位 S,指数位 E,尾数位M分别占了 1,11,52 位,并且在 ES5 规范 中指出了指数位E ...

  7. 保存数据到csv文件报错:Permission denied: './train_data.csv'

    如果你此前已经输出,创建了文件,很有可能是你打开了此文件,导致写入不进去报错,关掉文件重新运行程序即可!

  8. 【Java】Debug断点调试常用技巧

    Debug操作技巧 Show Execution Point 将光标回到当前断点停顿的地方 Step Over 执行当前行代码,并将运行进度跳转到下一行. Step Into 进入到当前代码行的方法内 ...

  9. Git操作文档

    Git 操作文档 Git 是一个十分流行的版本控制系统,Git 和 SVN 区别在于,SVN使用增量文件系统,存储每次提交之间的差异.而 git 使用全量文件系统,存储每次提交的文件的全部内容(sna ...

  10. mybatis-generator的使用心得

    之前开发了一个亚健康测评系统,使用的是SSM框架,里面第一次使用到了mybatis-generator逆向代码生成工具,很方便,省去了基本的增删改查的mapper文件及sql的编写,还能避免错误,这里 ...