英文:
Swift compiler or framework bug?
问题
以下是一个简单的代码,用于在2D多边形中插入额外的点。它永远不会终止(在Xcode 14.3、iOS 16.4.1(a)上)。问题在注释中有解释 —— 看起来在 polygon.insert
后,如果插入的索引等于 polygon.count
,polygon.count
返回错误的值。这真的不能是编译器/框架的错误,我漏掉了什么?
//
// ViewController.swift
// CompilerBug?
//
import UIKit
import simd
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var polygon = [SIMD3<Float>(1.345, 0.0, 0.002), SIMD3<Float>(1.181, 0.0, -0.171), SIMD3<Float>(1.185, 0.0, -0.206), SIMD3<Float>(1.141, 0.0, -0.255), SIMD3<Float>(1.121, 0.0, -0.257), SIMD3<Float>(0.848, 0.0, -0.636), SIMD3<Float>(0.777, 0.0, -0.604), SIMD3<Float>(0.692, 0.0, -0.532), SIMD3<Float>(0.677, 0.0, -0.5), SIMD3<Float>(0.6976719, 0.0, -0.46364594), SIMD3<Float>(0.903, 0.0, -0.188), SIMD3<Float>(1.1739755, 0.0, 0.12979852)]
ViewController.addPoints(to: &polygon, every: 0.05)
}
static func addPoints(to polygon: inout [simd_float3], every d: Float) {
let threshold = d * d
var i = 0
while i < polygon.count {
let j = (i + 1) % polygon.count // "A"
while polygon[i].distanceSquared2D(polygon[j]) > threshold {
let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
y: 0.0,
z: (polygon[i].z + polygon[j].z) / 2.0)
// 当i+1等于polygon.count时,在插入后,“A”处的polygon.count调用返回的是插入前的计数!
polygon.insert(new, at: i + 1)
}
i += 1
}
}
}
extension simd_float3 {
public func distanceSquared2D(_ b: simd_float3) -> Float {
return (self.x - b.x) * (self.x - b.x) + (self.z - b.z) * (self.z - b.z)
}
}
英文:
Below is some simple code to insert additional points into a 2D polygon. It never terminates (on Xcode 14.3, iOS 16.4.1(a)). The cause is explained in the comments — it appears that polygon.count
returns the wrong value after polygon.insert
when the insertion index equals polygon.count
. This can't really be a compiler/framework bug surely, what am I missing?
//
// ViewController.swift
// CompilerBug?
//
import UIKit
import simd
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var polygon = [SIMD3<Float>(1.345, 0.0, 0.002),SIMD3<Float>(1.181, 0.0, -0.171),SIMD3<Float>(1.185, 0.0, -0.206),SIMD3<Float>(1.141, 0.0, -0.255),SIMD3<Float>(1.121, 0.0, -0.257),SIMD3<Float>(0.848, 0.0, -0.636),SIMD3<Float>(0.777, 0.0, -0.604),SIMD3<Float>(0.692, 0.0, -0.532),SIMD3<Float>(0.677, 0.0, -0.5),SIMD3<Float>(0.6976719, 0.0, -0.46364594),SIMD3<Float>(0.903, 0.0, -0.188),SIMD3<Float>(1.1739755, 0.0, 0.12979852)]
ViewController.addPoints(to: &polygon, every: 0.05)
}
static func addPoints(to polygon: inout [simd_float3], every d: Float) {
let threshold = d * d
var i = 0
while i < polygon.count {
let j = (i + 1) % polygon.count // "A"
while polygon[i].distanceSquared2D(polygon[j]) > threshold {
let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
y: 0.0,
z: (polygon[i].z + polygon[j].z) / 2.0)
// when i+1 equals polygon.count, the subsequent call to polygon.count at "A"
// after insertion returns the count prior to the insertion!
polygon.insert(new, at: i + 1)
}
i += 1
}
}
}
extension simd_float3
{
public func distanceSquared2D(_ b: simd_float3) -> Float {
return (self.x - b.x) * (self.x - b.x) + (self.z - b.z) * (self.z - b.z)
}
}
答案1
得分: 1
Here is the translation of the code part you provided:
"不清楚您认为代码应该执行什么操作,但如果您使用 print
语句进行仪器测量,您将看到它是以逻辑和一致的方式运行的:
while i < polygon.count {
print(i, polygon.count)
let j = (i + 1) % polygon.count
while polygon[i].distanceSquared2D(polygon[j]) > threshold {
let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
y: 0.0,
z: (polygon[i].z + polygon[j].z) / 2.0)
print("insert")
polygon.insert(new, at: i + 1)
}
i += 1
}
每当第一个 print
语句打印时,我们看到 "insert"
被打印的次数和 polygon.count
的增加总是相同的。因此,一个 insert
就是一个增加的 polygon.count
,这是预期的(我假设也是期望的)。
然后当我们达到 i
为60和 polygon.count
为61时,内部的 while
循环会一直运行(我们会不断看到 "insert"
的输出,而不再返回到第一个 print
),从而导致应用程序挂起。
因此,我看到的唯一错误,如果这不是您期望的结果,那就是您的程序本身。我猜想问题可能出在条件
polygon[i].distanceSquared2D(polygon[j]) > threshold
因为 i
和 j
都没有改变,插入操作现在是在 j
的位置进行的。"
英文:
Unclear what you think your code is supposed to do, but if you instrument it with print
statements you will see it is behaving logically and consistently:
while i < polygon.count {
print(i, polygon.count)
let j = (i + 1) % polygon.count
while polygon[i].distanceSquared2D(polygon[j]) > threshold {
let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
y: 0.0,
z: (polygon[i].z + polygon[j].z) / 2.0)
print("insert")
polygon.insert(new, at: i + 1)
}
i += 1
}
Every time the first print
statement prints, we see that the number of times "insert"
was printed and the increase in polygon.count
are always the same. So one insert
is one increment in polygon.count
, which is as expected (and, I presume, desired).
Then when we reach i
at 60 and polygon.count
at 61, the inner while
loop runs forever (we get a steady stream of "insert"
without every coming round to the first print
again) and so the app hangs.
So the only bug I see, if that's not the outcome you expect, is in your program itself. I suppose that the problem is that the condition
polygon[i].distanceSquared2D(polygon[j]) > threshold
just runs away with you, because neither i
nor j
changes and the insertions are now taking place at the j
position.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论