typescriptfloating-pointgeometrylineprecision# Is it correct and consistent to check two vertex points for equality?

I am writing a Typescript game where there are vertexes drawn to a canvas, and some edges coming from them. I want to determine if some of edges from different vertexes intersect. For this, I am using a generic `doLinesIntersect`

function to determine if two edges intersect.

However, the problem is that it shows all lines as intersecting, because if two edges share a vertex, they compute as always intersecting, but I do not want this. I was able to get it "working" by checking manually to see if they share a vertex like so:

```
function doLinesTrulyIntersect(aX1: number, aY1: number, aX2: number, aY2: number, bX1: number, bY1: number, bX2: number, bY2: number): boolean {
const sharesVertexes = (aX1 === bX1 && aY1 === bY1) ||
(aX1 === bX2 && aY1 === bY2) ||
(aX2 === bX1 && aY2 === bY1) ||
(aX2 === bX2 && aY2 === bY2);
return !sharesVertexes && doLinesIntersect(
aX1, aY1, aX2, aY2,
bX1, bY1, bX2, bY2
);
}
```

Basically, if two edges share a vertex, then they do not intersect.

But, will this always work? The logic is that since if two edges have the same vertex, then (because they're the same point), floating point equality testing should work, right? It's the exact same bits under the hood, after all.

However, I know that in general testing two floating points for equality is incorrect and inconsistent, but does that apply in this case?

Solution

If an endpoint *X* in one edge and an endpoint *Y* in another edge are set equal to the same point *P*, then *X* equals *Y*. Floating-point entities are not mystical entities that vary spontaneously, and testing for equality reports two things are equal if and only if they are equal.

When you see cautions about comparing floating-point numbers for equality, the actual problem is about comparing any kind of approximations, not anything particular to floating-point arithmetic. Suppose there is some ideal number *N* and we have two approximations *A* and *B* to *N*. Will *A* and *B* be equal? Quite possibly not, because preparing two approximations in different ways will often produce different results. To estimate the percentage of the US population that has blue eyes, you might go out and sample 1,000 people and come up with some percentage *A*, and another person might go out and sample 1,000 other people and come up with some percentage *B*. Even though both of these are approximations of *N*, they are quite likely not equal.

The reason this arises as a problem in floating-point arithmetic is that floating point was primarily designed to **approximate** real-number arithmetic, and it is primarily used for that. Note that it is floating-point **arithmetic** that approximates real-number arithmetic. Floating-point **numbers** are actual real numbers (a subset of them). There is nothing approximate or otherwise wonky about the numbers: Each floating-point number is exactly one real number. When you set a floating-point variable to a floating-point number, it retains that number. It does not change or become approximate.

It is the process of calculating with floating-point numbers that introduces approximations and rounding errors: Most floating-point operations, including addition and other arithmetic, scientific functions, and converting to a floating-point format from decimal (including decimal numerals in source code or program input) are operations that may round their results to fit in the floating-point format.

Note that the above is actually true of **any** numerical format. Calculations with fixed-point numbers also produce rounded results, when the exact mathematical result does not fit in the format. And calculations with integers are also adjusted to fit in the integer format. `7/3`

in integer arithmetic produces 2, an error greater than 1 part in 10, whereas `7./3.`

in “double precision” floating-point has an error less than 1 part in a quadrillion. So integer arithmetic can be much worse for rounding errors than floating-point arithmetic. The reason people caution about floating-point rounding and not integer rounding is due to the predominant ways we use these formats, not due to their intrinsic susceptibility to errors.

Further, once you are working with approximations, all of your results are approximate. You can get very large relative errors by subtracting two nearly equal numbers. People warn about comparison because it is one operation that novices may misuse. But anytime you are working with approximations, in any format, you should be aware of what errors can happen and how large they can be.

All of the above is to give you context for determining what operations you can rely on. If you set two endpoints to the same point and later compare them, they will compare as equal.

Some things that could go wrong in the problem you describe are:

- You do not set the two endpoints to the same point in the first place.
- Something changes the value(s) of one or both endpoints.
- There is a comparison between something computed and an endpoint, rather than between the two endpoints directly. For example, if we have an edge XY and an edge YZ with common endpoint Y, and some software calculates where they intersect, those calculations might produce a point Y' that is slightly different from Y.

- Why do I only get an error for a union but not for a bare type?
- Cannot set a value for an object of type `React.CSSProperties` with key `keyof React.CSSProperties`
- How To Specify Which Module to add Controller to in NestJS CLI?
- Property 'data' does not exist on type 'Promise<void | AxiosResponse>
- D3 - line plot from bar chart example
- Typescript writing RequiredProps generic using conditional types
- Javascript - Elements added into an array not in correct place
- How can typescript import external modules in a web worker
- typeORM combine next.js can not connect database with error
- Missing parameter(s): email, password error is occurring on posting data in angular4?
- How can I solve the error 'TS2532: Object is possibly 'undefined'?
- How do I import npm types to Deno?
- Programmatic Webpack & Jest (ESM): can't resolve module without '.js' file extension
- Why would some arbitrary key be "missing" from a Record<string,any>?
- Playwright works in headful mode but fails in headless
- UniqArray infer wrong type
- How to make prop mandatory based on another prop being passed
- How to Validate Drop down value in playwright
- Can a type that has an object format have a conditional type as a value based on another index of itself?
- Creating zip file from image blobs on a content script of firefox extension
- How to specify in TypeScript that a property is a typeof an object that extends another?
- Using multer and express with typescript
- Understanding FetchAPI in vue + TS
- Flatten array of arrays in TypeScript
- Getting [TS] errors for files inside the node_modules folder
- How to get a component type so I can use it in a typescript interface - Vue 3
- react native typescript screen test returning Test suite failed to run AsyncStorage is null
- Why is the value from the input immediately displayed? How to fix it?
- Typescript target warnings after Angular 15 update
- Property 'props' does not exist on type IntrinsicAttributes & string[]