## Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

### Re: Coding: Fleeting Thoughts

So the a plus delta times t works in general for two points. But the general thing is that while vector spaces like linear combinations, affine spaces like affine combinations. That is where the coefficients add up to one.

Ie if you have n points, any weighted average of these points is in the space.

Doing that using deltas is awkward. Well somewhat: you pick one point as your zero, subtract it from the others, scale each delta by the weight, then add it back to your zero.

But really much like how scalar multiplication and vector addition is a mini linear combination, having some kind of affine combination primitive might be nice.

(I hope I got the terminology right, this is barrel scraping my memory)
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

### Re: Coding: Fleeting Thoughts

Xanthir wrote:
Sc4Freak wrote:I've never liked the idea of making the distinction between points and vectors. There's a mathematical difference, but trying to enforce that through the type system just leads to annoyance and frustration in practice.

I've used frameworks that do try to enforce it, and invariably I always run into a situation where I try to do something which I would expect to work but doesn't because of overzealous restrictions. If I want to find the midpoint of two points, the usual trivial formula is (a + b) / 2. If a and b are of a specialized Point class that forbids addition of Points, then you either have to do it manually with each of the components or you have to convert them to Vector objects first. There are many many examples of this type of thing, and I don't see how (Vector(a) + Vector(b)) / 2 is any clearer than (a + b) / 2. So I just treat vectors as vectors and points as vectors and be done with it.

Funnily enough, this example shows clearly why you *shouldn't* mix vectors and points. This kind of math *only* works if you're trying to find the centroid of multiple points (the midpoint when it's only two). If you wanted to, say, find the point 1/3 of the way from A to B, it wouldn't work at all.

Well yes... that's because I'm trying to find the midpoint and not the point 1/3 of the way from A to B! Obviously the midpoint formula doesn't work if you're not trying to find the midpoint, but I don't see why that's a reason not to use it unless you actually need the general solution. It's for the same reason I have no qualms using x * x instead of pow(x, 2) - it's abundantly clear what x * x does and the more general pow() doesn't buy me anything.

Xanthir wrote:

Code: Select all

`// The point halfway between a and bVector.between(a,b).scale(.5).projectFrom(a)// The point 1/3 of the way between a and bVector.between(a,b).scale(.333).projectFrom(a)`

I think that's as good of an argument against it as any... I certainly don't think that "Vector.between(a,b).scale(.5).projectFrom(a)" is a very elegant way to express "the midpoint between a and b". Anybody who understands that will certainly understand (a+b)/2 - which does the same thing except more succinctly and with easier understanding.

PM 2Ring
Posts: 3707
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

### Re: Coding: Fleeting Thoughts

troyp wrote:
PM 2Ring wrote:The ease of composition of transformations is a major motivation for using 4D homogeneous coordinates in computer graphics. Another nice property is that points at infinity can easily be represented (by making the last component 0) and transformed. (In projective geometry, each direction is identified with a point at infinity: it's the point where all lines of a given direction meet). So by working in homogeneous coordinates we simplify the code needed to cope with points at infinity.

That's interesting. I've never gotten around to learning projective geometry. I'll have to have a closer look at the Wikipedia article later. So is the idea that translations are rotations around a point at infinity?

I'd like to say yes, but I'm too lazy to do the algebra to prove it. Most tutorials on homogeneous coordinates don't bother with such things, since it's so easy to show that a translation matrix performs as advertised.

mr-mitch
Posts: 477
Joined: Sun Jul 05, 2009 6:56 pm UTC

### Re: Coding: Fleeting Thoughts

Making points immutable is always fun, but it can hurt the interpretation of lines and planes (etc) and automobiles. For example you can represent the equation of a line as a point r on the line, a parameter t, and a vector parallel to the line v. Thus L(t) = r + tv.

But if I can't add things to points, what is r + tv? Am I allowed to add vectors to points?

But what if I want to find the intersection of two lines?

L(t) = M(s) = r + tv = p + sq.

If I can't subtract or add points, how do I solve this equation for t, and s?

I suppose you could say you're just interpreting it as a set of linear equations. I suppose that's okay, but what's the point if you can't just treat them as vectors/matrices?

jaap
Posts: 2094
Joined: Fri Jul 06, 2007 7:06 am UTC
Contact:

### Re: Coding: Fleeting Thoughts

mr-mitch wrote:Am I allowed to add vectors to points?

Yes.
mr-mitch wrote:L(t) = M(s) = r + tv = p + sq.

If I can't subtract or add points, how do I solve this equation for t, and s?

You cannot add points, but you can subtract two points to get a vector. Conversely, you can add a vector to a point, to get another point.
When solving that equation, you may interpret r and p as points as they will get subtracted when you move them to one side of the equation, leaving you with a pure vector equation. Usually though, they are considered vectors too, defined as the difference between the point and some arbitrarily chosen point called the origin.

Steax
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

### Re: Coding: Fleeting Thoughts

Pagoda Box sounds interesting. I'd use it fully if it were more established. Giving a run for it now. It's like Heroku, but seems simpler to deploy PHP/MySQL stacks to.
In Minecraft, I use the username Rirez.

Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

### Re: Coding: Fleeting Thoughts

Steax wrote:Pagoda Box sounds interesting. I'd use it fully if it were more established. Giving a run for it now. It's like Heroku, but seems simpler to deploy PHP/MySQL stacks to.

But it requires you to use PHP. If you're going to be doing Heroku-like installs anyway, instead of just copying files to a shared web host, why limit yourself to PHP?
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

Steax
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

### Re: Coding: Fleeting Thoughts

My clients still want plain PHP/MySQL/memcache for portability, apparently. So I still get the good parts of a scaling/managed PaaS.
In Minecraft, I use the username Rirez.

Ptolom
Posts: 1559
Joined: Mon Mar 24, 2008 1:55 pm UTC
Location: The entropy pool
Contact:

### Re: Coding: Fleeting Thoughts

Today I discovered a header file which includes itself does exactly what it looks like it does. Or at least until gcc stops it after 200 iterations.

The Great Hippo
Swans ARE SHARP
Posts: 7361
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

### Re: Coding: Fleeting Thoughts

I'm doing some basic coding work and I had a weird math question. I noticed when I did some of my float comparison operations (float1 == float2?), I got some unusual errors, so I looked it up and found out that float comparison is a tricky thing. My solution, then, was to round the floats I'm using to 6 places away from the decimal point (1.5465326 becomes 1.546533).

I'm worried, though. In order for my calculations to remain consistent, I'm going to have to apply this rounding method to all my floats in the linear algebra equations I'm doing. In otherwords, whenever a new vector or length is generated, it needs to be rounded in this way. I might also have to round dot products this way (still looking into it). Is six decimal points enough for most rigorous linear algebra equations? Is there an easier way to do float comparisons than just rounding all your floats?

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

### Re: Coding: Fleeting Thoughts

Subtracting the floats and checking that the absolute value is less than some tolerance is the standard technique, I believe.

WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

### Re: Coding: Fleeting Thoughts

The Great Hippo wrote:I'm doing some basic coding work and I had a weird math question. I noticed when I did some of my float comparison operations (float1 == float2?), I got some unusual errors, so I looked it up and found out that float comparison is a tricky thing. My solution, then, was to round the floats I'm using to 6 places away from the decimal point (1.5465326 becomes 1.546533).

I'm worried, though. In order for my calculations to remain consistent, I'm going to have to apply this rounding method to all my floats in the linear algebra equations I'm doing. In otherwords, whenever a new vector or length is generated, it needs to be rounded in this way. I might also have to round dot products this way (still looking into it). Is six decimal points enough for most rigorous linear algebra equations? Is there an easier way to do float comparisons than just rounding all your floats?

The general rule of thumb* is that you should never compare floats using the == operator. Even if you're rounding, it depends on the rounding method whether the two floats will come out the same or not, if they were originally computed differently. A much better approach is to subtract one float from the other and check if the difference is within some tolerance.

As for whether rounding to six places is "enough" or not, that depends on your specific application (which you didn't tell us) and the precision you need. Note that if you're working with currency (probably not the case since you're using linear algebra) you should not be using binary floats at all.

(edit: ninja'd)

* As always, there are exceptions. For example, if you explicitly set a float variable to 0 when you initialize it, and then want to compare it to 0 to see if a value was assigned after initialization, this is possibly a legitimate use of the == operator.

The Great Hippo
Swans ARE SHARP
Posts: 7361
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

### Re: Coding: Fleeting Thoughts

Oho--I didn't think of the float-subtraction-check-absolute-value trick. That could definitely work--thanks! I'll have to set up a new equality operation or somesuch for that, but it should fix the problem very nicely.

EDIT: Couldn't I set up a 'custom float class' in Python so that every time I try an ==, it switches it out for this tolerance check instead? I think I could--looking into it now. I don't have a lot of experience modifying primitives (float is a primitive, right?), but this is a good opportunity to learn about it, I imagine.

EDIT-EDIT: Oops, apparently doing that means having to go and modify Python on the C-level. So I'll just institute a more piecemeal solution, I think.

WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

### Re: Coding: Fleeting Thoughts

The Great Hippo wrote:Oho--I didn't think of the float-subtraction-check-absolute-value trick. That could definitely work--thanks! I'll have to set up a new equality operation or somesuch for that, but it should fix the problem very nicely.

EDIT: Couldn't I set up a 'custom float class' in Python so that every time I try an ==, it switches it out for this tolerance check instead? I think I could--looking into it now. I don't have a lot of experience modifying primitives (float is a primitive, right?), but this is a good opportunity to learn about it, I imagine.

You certainly could do that, but I'm not sure if it's a good idea. There is no "standard" tolerance to compare (it depends on the application and may be different in different parts of the application), so hiding it away in a class may not be a good idea. It might be fun to do as practice on how to build such a class in Python, but certainly I wouldn't do it in production code.

By the way, if you haven't already, check out What Every Computer Scientist Should Know About Floating-Point Arithmetic.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

### Re: Coding: Fleeting Thoughts

The Great Hippo wrote:EDIT-EDIT: Oops, apparently doing that means having to go and modify Python on the C-level. So I'll just institute a more piecemeal solution, I think.

No, it doesn't. You can subclass float:

Code: Select all

`class MyFloat(float):    def __eq__(self, other):        return abs(self - other) < TOLERANCE`

WanderingLinguist wrote:You certainly could do that, but I'm not sure if it's a good idea. There is no "standard" tolerance to compare (it depends on the application and may be different in different parts of the application), so hiding it away in a class may not be a good idea. It might be fun to do as practice on how to build such a class in Python, but certainly I wouldn't do it in production code.

You could always use a global variable TOLERANCE and reset it when necessary. Or have the global overridden in certain scopes and use dynamic scoping to access the value in the calling context (by which I mean using "eval('TOLERANCE')" instead of "TOLERANCE").

Not that I'm really suggesting it. What would be a better idea is to use a

Code: Select all

`   def equals(self, other, epsilon=TOLERANCE):        return abs(self - other) < epsilon`
method where you can pass in the tolerance (or optionally use a default value). I probably wouldn't do that either, though, just because it's annoying subclassing default types (mainly because you don't get to use nice concise literals) - and Python doesn't let you monkey-patch builtin types.

Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

### Re: Coding: Fleeting Thoughts

Simpler would be to simply define a non-method function:

Code: Select all

`def almost_equal(left, right, within=0.00000001):    return abs(left - right) < within`

and then just use that when you would normally use ==. No need to subclass anything.
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

### Re: Coding: Fleeting Thoughts

Aaeriele wrote:Simpler would be to simply define a non-method function:

Code: Select all

`def almost_equal(left, right, within=0.00000001):    return abs(left - right) < within`

and then just use that when you would normally use ==. No need to subclass anything.

It would, wouldn't it?

You'll have to excuse me. I've been coding in goddam Java for the last day and I've got methods on the mind.*

* "equals" methods especially. I was looking for a bug for ages and it turned out the problem was using == instead of .equals(). I'd overridden an equals() method thinking it overloaded the == operator, but it turned out it was just a regular method of Object.

Of course, posting this now, it's coming back to me that Java doesn't even have operator overloading. A fine time to remember that now...

PM 2Ring
Posts: 3707
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

### Re: Coding: Fleeting Thoughts

Aaeriele wrote:Simpler would be to simply define a non-method function:

Code: Select all

`def almost_equal(left, right, within=0.00000001):    return abs(left - right) < within`

and then just use that when you would normally use ==. No need to subclass anything.

That's what I'd normally do (or its equivalent in C or JavaScript). But lately I've been using Python's arbitrary precision mpmath package, which has a nice function called almosteq().

b.i.o
Green is the loneliest number
Posts: 2519
Joined: Fri Jul 27, 2007 4:38 pm UTC
Location: Hong Kong

### Re: Coding: Fleeting Thoughts

I actually think the most robust-in-the-face-of-people-making-stupid-mistakes solution would be to add a custom float class, have the __eq__ method raise an exception* when it's called, and then add an .almost_equals method that takes an optional tolerance variable and raises an exception if both of the args aren't instances of your custom float class. This way you won't accidentally call '==' when you mean 'almost_equals', the semantics are clear from the comparison call, you can have your tolerance variable, and it will help you find places where you forget to wrap your floats in your custom float class (which might possibly lead to errors elsewhere) because it'll fail.

(Depending on the size/complexity of your application this is possibly overkill.)

*it might be nicer to have it log the error somewhere rather than actually failing.

Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

### Re: Coding: Fleeting Thoughts

b.i.o wrote:I actually think the most robust-in-the-face-of-people-making-stupid-mistakes solution would be to add a custom float class, have the __eq__ method raise an exception* when it's called, and then add an .almost_equals method that takes an optional tolerance variable and raises an exception if both of the args aren't instances of your custom float class. This way you won't accidentally call '==' when you mean 'almost_equals', the semantics are clear from the comparison call, you can have your tolerance variable, and it will help you find places where you forget to wrap your floats in your custom float class (which might possibly lead to errors elsewhere) because it'll fail.

(Depending on the size/complexity of your application this is possibly overkill.)

*it might be nicer to have it log the error somewhere rather than actually failing.

I'd consider that incredibly overengineered for anything except maybe NASA code (and they generally don't use Python). For instance, it means that instead of doing...

Code: Select all

`almost_equals(2.0 / my_var, 5.0)`

you'd have to do...

Code: Select all

`Float(2.0 / my_var).almost_equals(Float(5.0))`

which is ridiculously verbose.
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

b.i.o
Green is the loneliest number
Posts: 2519
Joined: Fri Jul 27, 2007 4:38 pm UTC
Location: Hong Kong

### Re: Coding: Fleeting Thoughts

Aaeriele wrote:

Code: Select all

`Float(2.0 / my_var).almost_equals(Float(5.0))`

which is ridiculously verbose.

If you're using it like that there's obviously no point. The idea is that every float you're working with is made into an instance of your custom class at the borders of your program. You should almost never have to write code that looks like this.

Although after some further thought I think I'd almost certainly just override the __eq__ function and then add another almost_equals method with a tolerance variable. (With everything else I described the same.) That way you get the convenience and brevity of just using '==', which I think is worth it.

Anyway, I don't think it's over-engineered unless your program is a short one-off script, and then this whole discussion is pointless anyway. It's not a whole lot more work (really, it's not, if your code is structured reasonably and there aren't tons of random places with IO happening) than the implement-a-global-function solution, it's a lot more robust, and the kinds of errors you'll have when you forget what you're doing by accident will be the kind that are a pain to track down.

phlip
Restorer of Worlds
Posts: 7569
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

### Re: Coding: Fleeting Thoughts

Note to self:

Code: Select all

`fields = BaseClass.fields + [extra, fields, here]`
is very different to

Code: Select all

`fields = BaseClass.fields = [extra, fields, here]`

Code: Select all

`enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}`
[he/him/his]

Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

### Re: Coding: Fleeting Thoughts

Don't be silly. Those are two identical lines that don't differ in the slightest.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

### Re: Coding: Fleeting Thoughts

Yakk wrote:Don't be silly. Those are two identical lines that don't differ in the slightest.

I didn't realize modern programming languages were so sensitive to the mere 90-degree rotation of one measly line segment.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

### Re: Coding: Fleeting Thoughts

This reminds me of times I've repeatedly missed a typo in code and my brain's adjusted to seeing the line as I meant it rather than as it was, with the result that it's become increasingly likely to miss on successive attempts. There were times it was so extreme that I localized a bug to a short line but still couldn't see it despite slowly scanning it from start to finish. I had to resort to cutting the line and retyping the supposedly identical line (just to check it works and I'm not crazy) - then diffing the two lines char by char (visually or programmatically) to locate the error.

Coming back to the program later would negate the effect.

Xanthir
My HERO!!!
Posts: 5400
Joined: Tue Feb 20, 2007 12:49 am UTC
Contact:

### Re: Coding: Fleeting Thoughts

Yeah, the best way to fix those bugs is to just delete and re-type the line. We humans are stupid.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

### Re: Coding: Fleeting Thoughts

The galling thing is, my brain probably fancies itself sophisticated with its caching and its interpolation. Insufferable organ.

I just wish I could turn its "optimizations" off.

mr-mitch
Posts: 477
Joined: Sun Jul 05, 2009 6:56 pm UTC

### Re: Coding: Fleeting Thoughts

WanderingLinguist wrote:
Yakk wrote:Don't be silly. Those are two identical lines that don't differ in the slightest.

I didn't realize modern programming languages were so sensitive to the mere 90-degree rotation of one measly line segment.

It's an edge case.

Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

### Re: Coding: Fleeting Thoughts

troyp wrote:This reminds me of times I've repeatedly missed a typo in code and my brain's adjusted to seeing the line as I meant it rather than as it was, with the result that it's become increasingly likely to miss on successive attempts. There were times it was so extreme that I localized a bug to a short line but still couldn't see it despite slowly scanning it from start to finish. I had to resort to cutting the line and retyping the supposedly identical line (just to check it works and I'm not crazy) - then diffing the two lines char by char (visually or programmatically) to locate the error.

Coming back to the program later would negate the effect.

Another solution is to read your code backwards. This stops your brain from filling in what it expects, because it isn't used to reading backwards.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

### Re: Coding: Fleeting Thoughts

That is at best a short term solution, before you get used to reading your code backwards.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

### Re: Coding: Fleeting Thoughts

And in Prolog it just makes the problem worse!
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

### Re: Coding: Fleeting Thoughts

phlip wrote:Note to self:

Code: Select all

`fields = BaseClass.fields + [extra, fields, here]`
is very different to

Code: Select all

`fields = BaseClass.fields = [extra, fields, here]`

Yeah, I once had a bug that was in essence:

var = foo() | offset;

When it should have been

var = foo() + offset;

The killer was that with the version of the library that provided foo() that I was working with, the lower bits of the return value of foo() were always 0 so it worked. It was only when we upgraded to a new version of libfoo that things exploded in strange and wonderful ways.

tastelikecoke
Posts: 1208
Joined: Mon Feb 01, 2010 7:58 am UTC
Location: Antipode of Brazil
Contact:

### Re: Coding: Fleeting Thoughts

Yakk wrote:That is at best a short term solution, before you get used to reading your code backwards.

You can always read it upside down, mirror, or sideways. I don't advise coding with a mirror though.

FT: Doing 2D linear algebra stuff in C++ for Uva, and learned that vertical lines and horizontal lines will make your solution go NaN.
This makes me wonder how to code integration. I'll be needing that very soon (the crowbars are so scary).

Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

### Re: Coding: Fleeting Thoughts

sourmìlk wrote:And in Prolog it just makes the problem worse!

LOL
tastelikecoke wrote:This makes me wonder how to code integration. I'll be needing that very soon (the crowbars are so scary).

Took me a few seconds to realise what you meant by the crowbars.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

The Great Hippo
Swans ARE SHARP
Posts: 7361
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

### Re: Coding: Fleeting Thoughts

I've had a weird thought, and I wanted to ask about it and see if it's worth pursuing:

In the primitive linear algebra library I'm toying with (in python), I've added a system (as suggested and advised in this thread!) to test for float equality using a certain modifiable tolerance (approximate equality rather than direct equality). In the process, it occurred to me that I could define the equality constructor for my vector objects to allow for vector equality tests.

Which got me to thinking: Obviously, vectors that differ in the number of components pose an equality test problem (how can you accurately test the equality of V1(3,3) versus V2(3,3,3)?). But then it occurred to me: This might actually be a great way to test if a given vector falls on a given line or plane.

If the equality test assumes that non-present components are always zero, it can test V1(3,3,3) versus V2(3,3) (it would test false, since V2(3,3,0) does not equal V1(3,3,3)). And going the other way, if the equality test ignored additional components, you could test V2(3,3) vs V1(3,3,3) and get 'True' (since it would only look at the first two components, and ignore the third). Which is just a fancy way of saying V1(3,3,3) is a point on the line represented by V(3,3), right?

This would lead to assymetric equality, I guess (a == b does not imply b == a), which is probably pretty dangerous since that seems like a fundamental building block of mathematics, and my code probably shouldn't fuck up the fundamentals. But I get the vibe that this process isn't extraordinarily different than what I already do to test for a point on a line, and it kinda intrigues me. I'd appreciate any thoughts (particularly those along the lines of why this is a terrible, horrible idea!).

EDIT: Ooooor... I could just set it up so that it treats the 'lower' vector (the vector with the least amount of components) as the one that defines the number of components we test for. So a == b does imply b == a, as far as my vectors would be concerned. It would also allow for me to test if a given vector falls on a given plane. I'd need to figure out how the translation works so I could define arbitrary planes and stuff, though (as it is, I could only test for lines and planes and such that fall directly on the axis of a vector). Which leaves me wondering if this is really a shortcut. It certainly looks cleaner... The more I think about this, though, the more it strikes me as a dead end.

Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

### Re: Coding: Fleeting Thoughts

Two vectors with a different number of components are not equal. Other paths lead to madness. Really.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

The Great Hippo
Swans ARE SHARP
Posts: 7361
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

### Re: Coding: Fleeting Thoughts

Yeah--it just hit me when I started playing around with it, the only thing I could do is create lines, planes, and areas with a span dictated by the order of the components. I don't even think there's a translation scheme that could solve that problem, but if there was, it would probably end up being insane on the order of several magnitudes.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

### Re: Coding: Fleeting Thoughts

Yakk wrote:Two vectors with a different number of components are not equal. Other paths lead to madness. Really.

Asymmetric equality is madness. Equality of vectors with different numbers of components is just poor taste.

Perhaps not even that. If for some reason you were using vectors in R2 and R3 at the same time, with the R2 embedded in the R3, then it really would be appropriate to treat (3, 3) and (3, 3, 0) as the same vector**. Of course, that's leaving aside the question of whether it would be justified to use the two representations in the first place, but that doesn't seem inherently unreasonable.

Really, I think it's at least potentially sensible to use == for pretty much any equivalence relation*. It just depends on the context.

* at least in a language where you don't have user-defined operators to use instead.

edit:
** One problem with using this for equality is you can't use == to test if two vectors are "equivalent objects". You'd have to test their types as well, or define another method, or just do without the test (you could always use an == test instead and then cast to the appropriate class if necessary).

Ideally, if objects of two classes can be equal, the two classes should be "interchangeable" in the sense that you can always substitute an object of class1 by an equal object of class2.

The Great Hippo
Swans ARE SHARP
Posts: 7361
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

### Re: Coding: Fleeting Thoughts

What about an object that could be used in lieu of a float/integer, and behaved in a particular way for equality tests--always returning true, for example?

Sticking the object inside of a vector's component would then allow you to define something like 'V(3,OBJ,8)' (obj is the equality object), which would lead to any comparisons between a vector of (3, X, 8) returning 'True'. Vector equivalency would then be tested like normal (it would have to have the same amount of components to be coherent, but all equality tests for a value of this object automatically return true).

jaap
Posts: 2094
Joined: Fri Jul 06, 2007 7:06 am UTC
Contact:

### Re: Coding: Fleeting Thoughts

The Great Hippo wrote:What about an object that could be used in lieu of a float/integer, and behaved in a particular way for equality tests--always returning true, for example?

Sticking the object inside of a vector's component would then allow you to define something like 'V(3,OBJ,8)' (obj is the equality object), which would lead to any comparisons between a vector of (3, X, 8) returning 'True'. Vector equivalency would then be tested like normal (it would have to have the same amount of components to be coherent, but all equality tests for a value of this object automatically return true).

This equality is not transitive, so you have
(3, 1, 8) == (3, X, 8)
and
(3, X, 8) == (3, 2, 8)
but
(3, 1, 8) != (3, 2, 8)
This behaviour is not what you expect from "equals" and so can lead to problems when transitivity is assumed, for example if you use these vectors inside collections such as sets or maps, or other contexts where duplicates are not allowed. Note however that the same is true of the 'approximately equals' for floating point numbers. Implementing such not-quite-equals tests is fine, but it is an extremely bad idea to overload the actual equality operator with something that does not behave like equals.