Comparing two CGPoints for equality: returning not equal for two objects that output same point?

扶醉桌前 提交于 2020-12-01 11:48:10

问题


According to this question, using == and != should let you check for equality between two CGPoint objects.

However, the code below fails to consider two CGPoint objects as equal even though they output the same value.

What is the right way to check equality among CGPoint objects?

Code:

    let boardTilePos = boardLayer.convert(boardTile.position, from: boardTile.parent!)
    let shapeTilePos = boardLayer.convert(tile.position, from: tile.parent!)   
    print("board tile pos: \(boardTilePos). active tile pos: \(shapeTilePos). true/false: \(shapeTilePos == boardTilePos)")

Output:

board tile pos: (175.0, 70.0). active tile pos: (175.0, 70.0). true/false: false

回答1:


Unfortunately, what you see in the console is not what your real value is.

import UIKit

var x = CGPoint(x:175.0,y:70.0)
var y = CGPoint(x:175.0,y:70.00000000000001)

print("\(x.equalTo(y)), \(x == y),\(x),\(y)")

The problem is, the console only allows for 10-16 but in reality your CGFloat can go even lower than that because on 64bit architecture, CGFloat is Double.

This means you have to cast your CGPoint values to a Float if you want to get equality that will appear on the console, so you need to do something like:

if Float(boxA.x) == Float(boxB.x) && Float(boxA.y) == Float(boxB.y)
{
  //We have equality
}

Now I like to take it one step further.

In most cases, we are using CGPoint to determine points on the scene. Rarely do we ever want to be dealing with 1/2 points, they make our lives just confusing.

So instead of Float, I like to cast to Int. This will guarantee if two points are lying on the same CGPoint in scene space

if Int(boxA.x) == Int(boxB.x) && Int(boxA.y) == Int(boxB.y)
{
  //We have equality
}



回答2:


I'm providing an alternate answer since I don't agree with Knight0fDragon's implementation. This is only if you want to deal with factions of a point. If you only care about points in whole numbers, see Knight0fDragon's answer.

You don't always have the luxury of logging points to the console, or seeing if you're trying to compare points that are the victim of floating point math, like comparing (175.0, 70.0) to (175.0, 70.00001) (which both log as (175.0, 70.0) in the console). Yes, truncating to Int is a great way of understanding why two points that appear to print to the console as equal aren't. But it's not a catch all solution one should use for comparing every point. Depending on what level of precision you need, you want to take the absolute value of the difference of both x and y for each point, and see if it is in an acceptable range of a delta you specify.

var boxA = CGPoint(x:175.0, y:70.0)
var boxB = CGPoint(x:175.0, y:70.00000000000001)

let delta: CGFloat = 0.01

if (fabs(boxA.x - boxB.x) < delta) &&
   (fabs(boxA.y - boxB.y) < delta) {
    // equal enough for our needs
}

The answer to the question "What is the right way to check equality among CGPoint objects?" really depends on the way you compare floating point numbers.




回答3:


CGPoint provides its own comparison method: equalTo(_ point2: CGPoint)

Try this:

shapeTilePos.equalTo(boardTilePos)


来源:https://stackoverflow.com/questions/45449576/comparing-two-cgpoints-for-equality-returning-not-equal-for-two-objects-that-ou

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!