当前位置: 首页 > 面试题库 >

为什么在字典中双打的打印方式不同?

钮兴安
2023-03-14
问题内容
let dic : [Double : Double] = [1.1 : 2.3, 2.3 : 1.1, 1.2 : 2.3]

print(dic)// [2.2999999999999998: 1.1000000000000001, 1.2: 2.2999999999999998, 1.1000000000000001: 2.2999999999999998]



let double : Double = 2.3
let anotherdouble : Double = 1.1

print(double) // 2.3
print(anotherdouble) // 1.1

我不明白为什么编译器从字典中打印值会有所不同?我使用的是Swift 3,Xcode8。这是错误还是优化内容的怪异方法

编辑

更奇怪的是:

有些价值观过去了,有些则跌破了,有些则保持不变!1.1小于1.1000000000000001,而2.3大于2.2999999999999998,1.2仅为1.2


问题答案:

如注释中已经提到的,a Double不能1.1精确存储值。Swift根据IEEE
754
标准使用(像许多其他语言一样)二进制浮点数。

最接近的数目1.1可以被表示为Double

1.100000000000000088817841970012523233890533447265625

与最接近的数目2.3可以被表示,作为一个Double

2.29999999999999982236431605997495353221893310546875

打印 该数字表示将其再次转换为带有小数表示的字符串,并且以不同的精度完成此操作,具体取决于您如何打印该数字。

从源代码HashedCollections.swift.gyb一个可以看到description的方法
Dictionary使用debugPrint()两个键和值,和debugPrint(x)打印的值x.debugDescription
(如果x符合CustomDebugStringConvertible)。

另一方面,如果符合则print(x)呼叫。x.description``x``CustomStringConvertible

所以,你看到的是输出不同descriptiondebugDescriptionDouble

print(1.1.description) // 1.1
print(1.1.debugDescription) // 1.1000000000000001

从Swift源代码中,可以看到两者都使用Stubs.cpp中的swift_floatingPointToString()
函数,并且参数分别设置为和。此参数控制数字到字符串转换的精度:Debug``false``true

int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
  Precision = std::numeric_limits<T>::max_digits10;
}

有关这些常量的含义,请参见std ::
numeric_limits:

  • digits10 –可以不改变地表示的小数位数,
  • max_digits10 –区分此类型的所有值所必需的小数位数。

因此,description创建一个具有较少十进制数字的字符串。该字符串可以转换为a Double并返回给相同结果的字符串。
debugDescription创建具有更多十进制数字的字符串,以便任何两个不同的浮点值将产生不同的输出。



 类似资料:
  • 问题内容: 众所周知,(大多数)浮点数没有精确存储(使用IEEE-754格式时)。因此,不应这样做: ......因为它会导致,除非一些特定的任意精度的类型/类使用(BigDecimal的中的Java/Ruby的,bcmath时在PHP中,[数学::BigInt有 / 数学::BigFloat在Perl,仅举几例)来代替。 但是,我想知道为什么当尝试打印该表达式的结果时,脚本语言(Perl和PHP

  • 所以我有这个代码,叫我白痴哈哈,但是我不能让它打印7。 代码: 我需要知道如何改变与函数中的参数同名的变量。 任何帮助都将不胜感激,如果你不明白这个问题,我很乐意解释更多。

  • 问题内容: 我有以下代码: 如果我没有在goroutine中从缓冲区读取的代码,它会输出这样的消息,这是我期望发生的事情: 但是,将其放在goroutine中不会打印任何内容。 有人可以解释为什么吗? 问题答案: 函数完成后,您的程序将退出。这很可能在您的goroutine有时间运行并打印其输出之前发生。 一种选择是从通道读取主goroutine块,并在完成工作后将goroutine写入通道。

  • 问题内容: 我想知道当您尝试捕获StackOverflowError并提出以下方法时会发生什么: 现在我的问题是: 为什么此方法打印“ 4”? 我以为是因为在调用堆栈上需要3个段,但是我不知道3的来源。当您查看的源代码(和字节码)时,通常导致的方法调用要多于3(因此,调用堆栈上的3个段是不够的)。如果是由于优化而应用了Hotspot VM(方法内联),我想知道其他VM上的结果是否会有所不同。 编辑

  • 问题内容: 我想打印一个特定的Python字典键: 现在我可以检查是否可以,但是我想做的是打印密钥的名称。当然可以使用,但是我不想列出 所有 键,而只列出一个特定的键。例如,我期望这样的事情(用伪代码): 有什么方法可以打印键名? 编辑: 好的,非常感谢你们的反应!:)我意识到我的问题没有很好地表述和琐碎。我只是感到困惑,因为我意识到key_name是两个不同的东西,我认为从字典上下文中打印出来是

  • 我想知道当您试图捕获StackOverflowError时会发生什么,并提出了以下方法: 现在我的问题是: 为什么这个方法打印'4'? 我想可能是因为在调用堆栈上需要3个段,但我不知道3这个数字来自哪里。当您查看的源代码(和字节码)时,通常会导致比3个多得多的方法调用(因此调用堆栈中的3个段是不够的)。如果这是因为Hotspot VM应用的优化(方法内联),我想知道在另一个VM上结果是否会有所不同