473,407 Members | 2,315 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 software developers and data experts.

IComparer for floats? Heavy Math

Tom
Has anyone ever seen a IComparer for floats the returns magnitude.
i.e. instead of returning -1, it would return -5. To let you know HOW
different the two numbers are. obviously for int it is a - b. But for
float the results would have to be normalize some how to a 32bit
range. I understand there would be percision errors.

Thanks
Tom
Jul 21 '05 #1
8 2445
Tom,
You could use System.Math.Round, System.Math.Floor, or System.Math.Ceiling
to create your own...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63**************************@posting.google.c om...
Has anyone ever seen a IComparer for floats the returns magnitude.
i.e. instead of returning -1, it would return -5. To let you know HOW
different the two numbers are. obviously for int it is a - b. But for
float the results would have to be normalize some how to a 32bit
range. I understand there would be percision errors.

Thanks
Tom

Jul 21 '05 #2
Tom
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message news:<ur**************@TK2MSFTNGP09.phx.gbl>...
Tom,
You could use System.Math.Round, System.Math.Floor, or System.Math.Ceiling
to create your own...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63**************************@posting.google.c om...
Has anyone ever seen a IComparer for floats the returns magnitude.
i.e. instead of returning -1, it would return -5. To let you know HOW
different the two numbers are. obviously for int it is a - b. But for
float the results would have to be normalize some how to a 32bit
range. I understand there would be percision errors.

Thanks
Tom

Jul 21 '05 #3
Tom <ju********@hotmail.com> wrote:
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0


So you need to use Math.Floor for values < 0 and Math.Ceil for values >
0. That's not terribly tricky. You can still write your own reasonably
easily. The tricky bit is seeing whether the difference would overflow
or not. One way of doing that would be to halve both values, and if the
difference between *those* is greater than Float.MaxValue/2 or less
than -Float.MaxValue/2, then return Float.MaxValue or -Float.MaxValue.
Otherwise, return the difference.

I'd actually suggest that to keep things simple, you first check for
equality, and then work out which is greater. Then do the rest of the
calculations on the positive difference, and negate the result
appropriately at the end. That way you can deal with *just* Math.Ceil,
+Float.MaxValue etc.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #4
Tom,
In addition to Jon's comments.

What are you expecting from comparing .0 with .5 & 1.5 with 1? Or even .5
with -.5? If you define what you are expecting then we can recommend the
correct

Also are you wanting a Magitude function or a CompareTo, as Magitude is not
really the purpose of the CompareTo function...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63*************************@posting.google.co m...
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message

news:<ur**************@TK2MSFTNGP09.phx.gbl>...
Tom,
You could use System.Math.Round, System.Math.Floor, or System.Math.Ceiling to create your own...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63**************************@posting.google.c om...
Has anyone ever seen a IComparer for floats the returns magnitude.
i.e. instead of returning -1, it would return -5. To let you know HOW
different the two numbers are. obviously for int it is a - b. But for
float the results would have to be normalize some how to a 32bit
range. I understand there would be percision errors.

Thanks
Tom

Jul 21 '05 #5
Tom
I want the Magnitude of the difference. Say I have a series of floats

0.1 0.2 0.3 0.4 0.5 0.6

If I floor all these values they are 0.0 and all equal which is
obviously incorrect.

If I ceil all these values they are 1.0 and all equal which is also
obviously incorrect.

For fun lets also add the values.
1e+10 1e-10
now I compare .1 and .2 i with a normal compare I get 1
if I compare .1 and .3 I get 1
if I compare .1 and .5 I get 1
if I compare .1 and 1e+10 I get 1
if I compare .1 and 1e-10 I get -1

What I need to be able to do is say take 0.1 and 0.4 and 0.6
and say 0.4 is closer to 0.1 than 0.6

Obviously with just a series of floats this is trivial, the problem is
I am trying to accomplish this with a General Interface so I can apply
it to many types including classes, like ICompareable, which is how I
thought ICompareable was supposed to work. I didn't realize that -1 0
1 were the ONLY values that it return, even for ints.

Therefore I need to write a new interface that is similar to
IComparer, that will return the Magnitude of the differece. For ints
this is easy it's a-b. But for floats this is more difficult. How can
I write a function that will return a int representing the Magnitude
of the difference of floats, that will work for 1.0 and 1.1 but also
1e-10 and 1e+10 . i.e for 1.0 and 1.1 I may get a result of 5 but for
1e-10 and 1e+10 I may get a result of 500. The number itself isn't
important as long as it represents the magnitude of the diference up
to a certian percision. Possibly the int represents some sort of
logarythimic scale of the magnitude.

One way to solve this is to just have the interface return a float or
even a decimal instead of an int, then it would work for every type,
which is probably the right way to do this. I was just wondering if
this is some existing Mathimatical way, to normalize this difference
into the int range so a standard Comparer interface could be used.




"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message news:<ua**************@tk2msftngp13.phx.gbl>...
Tom,
In addition to Jon's comments.

What are you expecting from comparing .0 with .5 & 1.5 with 1? Or even .5
with -.5? If you define what you are expecting then we can recommend the
correct

Also are you wanting a Magitude function or a CompareTo, as Magitude is not
really the purpose of the CompareTo function...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63*************************@posting.google.co m...
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message

news:<ur**************@TK2MSFTNGP09.phx.gbl>...
Tom,
You could use System.Math.Round, System.Math.Floor, or System.Math.Ceiling to create your own...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63**************************@posting.google.c om...
> Has anyone ever seen a IComparer for floats the returns magnitude.
> i.e. instead of returning -1, it would return -5. To let you know HOW
> different the two numbers are. obviously for int it is a - b. But for
> float the results would have to be normalize some how to a 32bit
> range. I understand there would be percision errors.
>
> Thanks
> Tom

Jul 21 '05 #6
Tom,
I don't see that your Magnitude function can return an Int.

How does that saying go: You can't put a square peg in a round hole. (You
cannot preserve the fraction in an Int value...).
One way to solve this is to just have the interface return a float or
even a decimal instead of an int, then it would work for every type,
which is probably the right way to do this. I was just wondering if
this is some existing Mathimatical way, to normalize this difference
into the int range so a standard Comparer interface could be used. I would probably have it return a Decimal, although Single or Double may
also work:

http://www.yoda.arachsys.com/csharp/floatingpoint.html
http://www.yoda.arachsys.com/csharp/decimal.html

I suppose you could "normalize" the floats into Int64 values if there are
"significant" fractional parts. (if there is no integer difference, but
there is a fractional difference). However this may cause 11 with 21 to
return 10, while .011 and .021 also returns 10. Or you could "normalize" all
floats so that 11 & 21 return 10000, while .011 & .021 return 10.

Returning a Decimal, Single, Double or even a Quantity
(http://www.martinfowler.com/ap2/quantity.html) would allow you to return
the "Scale" of the difference along with the difference.

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63**************************@posting.google.c om... I want the Magnitude of the difference. Say I have a series of floats

0.1 0.2 0.3 0.4 0.5 0.6

If I floor all these values they are 0.0 and all equal which is
obviously incorrect.

If I ceil all these values they are 1.0 and all equal which is also
obviously incorrect.

For fun lets also add the values.
1e+10 1e-10
now I compare .1 and .2 i with a normal compare I get 1
if I compare .1 and .3 I get 1
if I compare .1 and .5 I get 1
if I compare .1 and 1e+10 I get 1
if I compare .1 and 1e-10 I get -1

What I need to be able to do is say take 0.1 and 0.4 and 0.6
and say 0.4 is closer to 0.1 than 0.6

Obviously with just a series of floats this is trivial, the problem is
I am trying to accomplish this with a General Interface so I can apply
it to many types including classes, like ICompareable, which is how I
thought ICompareable was supposed to work. I didn't realize that -1 0
1 were the ONLY values that it return, even for ints.

Therefore I need to write a new interface that is similar to
IComparer, that will return the Magnitude of the differece. For ints
this is easy it's a-b. But for floats this is more difficult. How can
I write a function that will return a int representing the Magnitude
of the difference of floats, that will work for 1.0 and 1.1 but also
1e-10 and 1e+10 . i.e for 1.0 and 1.1 I may get a result of 5 but for
1e-10 and 1e+10 I may get a result of 500. The number itself isn't
important as long as it represents the magnitude of the diference up
to a certian percision. Possibly the int represents some sort of
logarythimic scale of the magnitude.

One way to solve this is to just have the interface return a float or
even a decimal instead of an int, then it would work for every type,
which is probably the right way to do this. I was just wondering if
this is some existing Mathimatical way, to normalize this difference
into the int range so a standard Comparer interface could be used.




"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message

news:<ua**************@tk2msftngp13.phx.gbl>...
Tom,
In addition to Jon's comments.

What are you expecting from comparing .0 with .5 & 1.5 with 1? Or even ..5 with -.5? If you define what you are expecting then we can recommend the
correct

Also are you wanting a Magitude function or a CompareTo, as Magitude is not really the purpose of the CompareTo function...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63*************************@posting.google.co m...
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:<ur**************@TK2MSFTNGP09.phx.gbl>...
> Tom,
> You could use System.Math.Round, System.Math.Floor, or

System.Math.Ceiling
> to create your own...
>
> Hope this helps
> Jay
>
> "Tom" <ju********@hotmail.com> wrote in message
> news:63**************************@posting.google.c om...
> > Has anyone ever seen a IComparer for floats the returns magnitude.
> > i.e. instead of returning -1, it would return -5. To let you know

HOW > > different the two numbers are. obviously for int it is a - b. But for > > float the results would have to be normalize some how to a 32bit
> > range. I understand there would be percision errors.
> >
> > Thanks
> > Tom

Jul 21 '05 #7
Please explain for what do you need this? If you want to sort the values,
IComparer will be enough.
If you really want the magnitude of the difference, you have to state the
magnitude in double values,
you cannot express the difference of floating point number using integers.

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
"Tom" <ju********@hotmail.com> schrieb im Newsbeitrag
news:63**************************@posting.google.c om...
I want the Magnitude of the difference. Say I have a series of floats

0.1 0.2 0.3 0.4 0.5 0.6

If I floor all these values they are 0.0 and all equal which is
obviously incorrect.

If I ceil all these values they are 1.0 and all equal which is also
obviously incorrect.

For fun lets also add the values.
1e+10 1e-10
now I compare .1 and .2 i with a normal compare I get 1
if I compare .1 and .3 I get 1
if I compare .1 and .5 I get 1
if I compare .1 and 1e+10 I get 1
if I compare .1 and 1e-10 I get -1

What I need to be able to do is say take 0.1 and 0.4 and 0.6
and say 0.4 is closer to 0.1 than 0.6

Obviously with just a series of floats this is trivial, the problem is
I am trying to accomplish this with a General Interface so I can apply
it to many types including classes, like ICompareable, which is how I
thought ICompareable was supposed to work. I didn't realize that -1 0
1 were the ONLY values that it return, even for ints.

Therefore I need to write a new interface that is similar to
IComparer, that will return the Magnitude of the differece. For ints
this is easy it's a-b. But for floats this is more difficult. How can
I write a function that will return a int representing the Magnitude
of the difference of floats, that will work for 1.0 and 1.1 but also
1e-10 and 1e+10 . i.e for 1.0 and 1.1 I may get a result of 5 but for
1e-10 and 1e+10 I may get a result of 500. The number itself isn't
important as long as it represents the magnitude of the diference up
to a certian percision. Possibly the int represents some sort of
logarythimic scale of the magnitude.

One way to solve this is to just have the interface return a float or
even a decimal instead of an int, then it would work for every type,
which is probably the right way to do this. I was just wondering if
this is some existing Mathimatical way, to normalize this difference
into the int range so a standard Comparer interface could be used.

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message

news:<ua**************@tk2msftngp13.phx.gbl>...
Tom,
In addition to Jon's comments.

What are you expecting from comparing .0 with .5 & 1.5 with 1? Or even ..5 with -.5? If you define what you are expecting then we can recommend the
correct

Also are you wanting a Magitude function or a CompareTo, as Magitude is not really the purpose of the CompareTo function...

Hope this helps
Jay

"Tom" <ju********@hotmail.com> wrote in message
news:63*************************@posting.google.co m...
That would just give me 0 in most cases.

Round(.0-.5)=0
Round(1.5-1)=0

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:<ur**************@TK2MSFTNGP09.phx.gbl>...
> Tom,
> You could use System.Math.Round, System.Math.Floor, or

System.Math.Ceiling
> to create your own...
>
> Hope this helps
> Jay
>
> "Tom" <ju********@hotmail.com> wrote in message
> news:63**************************@posting.google.c om...
> > Has anyone ever seen a IComparer for floats the returns magnitude.
> > i.e. instead of returning -1, it would return -5. To let you know

HOW > > different the two numbers are. obviously for int it is a - b. But for > > float the results would have to be normalize some how to a 32bit
> > range. I understand there would be percision errors.
> >
> > Thanks
> > Tom

Jul 21 '05 #8
Tom <ju********@hotmail.com> wrote:
I want the Magnitude of the difference. Say I have a series of floats

0.1 0.2 0.3 0.4 0.5 0.6

If I floor all these values they are 0.0 and all equal which is
obviously incorrect.

If I ceil all these values they are 1.0 and all equal which is also
obviously incorrect.
I don't think anyone suggested applying Floor or ceil to the values
themselves - you'd apply Ceiling to the *difference* between them.
For fun lets also add the values.
1e+10 1e-10

now I compare .1 and .2 i with a normal compare I get 1
if I compare .1 and .3 I get 1
if I compare .1 and .5 I get 1
if I compare .1 and 1e+10 I get 1
if I compare .1 and 1e-10 I get -1

What I need to be able to do is say take 0.1 and 0.4 and 0.6
and say 0.4 is closer to 0.1 than 0.6

Obviously with just a series of floats this is trivial, the problem is
I am trying to accomplish this with a General Interface so I can apply
it to many types including classes, like ICompareable, which is how I
thought ICompareable was supposed to work. I didn't realize that -1 0
1 were the ONLY values that it return, even for ints.
It depends on the implementation. There may be some implementations
which return other values; there's certainly nothing to stop you from
writing one which *does* return other values, as the interface only
specifies it in terms of 0, less than 0 and greater than 0.
Therefore I need to write a new interface that is similar to
IComparer, that will return the Magnitude of the differece. For ints
this is easy it's a-b. But for floats this is more difficult. How can
I write a function that will return a int representing the Magnitude
of the difference of floats, that will work for 1.0 and 1.1 but also
1e-10 and 1e+10 . i.e for 1.0 and 1.1 I may get a result of 5 but for
1e-10 and 1e+10 I may get a result of 500. The number itself isn't
important as long as it represents the magnitude of the diference up
to a certian percision. Possibly the int represents some sort of
logarythimic scale of the magnitude.


A log does indeed sound like the way to go. I'd multiply the natural
log of the difference by 3 million and convert the result into an int.
That will use virtually the whole range of int to cover the whole range
of possible differences, assuming my maths is right. You should also
have a separate check that the result is only zero if the two numbers
actually *are* the same though - it's possible that the log of the
difference will be unrepresentably small, but the numbers themselves
aren't equal. You also need to be careful that the difference doesn't
overflow to start with.

That should guarantee that if the result of Compare between x and y is
greater than the result of Compare between y and z (and both are
positive) then z is closer to y than y is closer to x. It won't
guarantee the other way round, of course.

Oh, stuff it: here's some sample code. (It's interesting how many more
little problems showed up when I started coding it...)

using System;
using System.Collections;

class Test
{
static void Main()
{
LogDoubleComparer comp = new LogDoubleComparer();
// Test an extreme case...
Console.WriteLine (comp.Compare(Double.MaxValue,
Double.MinValue));
// And some less extreme ones
Console.WriteLine (comp.Compare(0.1, 0.4));
Console.WriteLine (comp.Compare(0.4, 0.6));
}
}

class LogDoubleComparer : IComparer
{
public int Compare (object a, object b)
{
if (! (a is double && b is double))
{
throw new ArgumentException
("LogDoubleComparer can only compare doubles");
}
double x = (double)a;
double y = (double)b;

// If they're equal, return 0 now, so we can assume for
// the rest of the method that they're not equal.
if (x==y)
{
return 0;
}

if (double.IsNaN(x) || double.IsInfinity(x) ||
double.IsNaN(y) || double.IsInfinity(y))
{
throw new ArgumentException
("LogDoubleComparer can't cope with NaN or infinity");
}

// Divide both by 2.5 to make absolutely sure we'll
// be able to calculate the difference without
// overflow

double c = x/2.5;
double d = y/2.5;

// Find the absolute value of the difference. We'll
// sort out the sign later.
double diff = Math.Abs(c-d);

// Add 2 to the difference to make sure the log is positive
// (We should now not be able to get a log result of 0,
// which is handy.)
diff += 2.0;

// log can now be NegativeInfinity (if diff is 0,
// or presumably if it's too close to zero to call)
// but shouldn't be NaN.
double log = Math.Log(diff);

// Now scale so that we get a wider range of values in int.
// We should still easily be within the range of int though.
log *= 3000000.0;

// Now convert to an int, taking the ceiling to make
// sure we don't actually return 0.
int ret = (int) Math.Ceiling(log);

// Now get the sign right - we need to invert if x < y
if (x < y)
{
ret = -ret;
}

return ret;
}
}

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Eric Gibson | last post by:
I could have sworn this would be a FAQ, but it doesn't appear to be in there. You must get this all the time, or I'm just totally doing something wrong. Math with int's and floats appears to...
12
by: BGP | last post by:
I am working on a WIN32 API app using devc++4992 that will accept Dow Jones/NASDAQ/etc. stock prices as input, parse them, and do things with it. The user can just cut and paste back prices into a...
8
by: Tom | last post by:
Has anyone ever seen a IComparer for floats the returns magnitude. i.e. instead of returning -1, it would return -5. To let you know HOW different the two numbers are. obviously for int it is a -...
10
by: INeedADip | last post by:
I am trying to use a generic (reflection) IComparer class to sort a generic list but I get the error: Unable to cast object of type 'GenericComparer' to type 'System.Collections.Generic.Icomparer...
10
by: Christoph Zwerschke | last post by:
Currently, if you write 3*'*', you will get '***', but if you write 3.0*'*', you will get an error (can't multiply sequence by non-int). I was wondering whether this should be allowed, i.e....
6
by: Andrea B | last post by:
Hi everybody, a guy told me during a job interview that we can't compare directly 2 floats, because in very rare situations we can get wrong results. I googled it, with no result. Do you know...
1
by: Brett Romero | last post by:
What are the reasons to use one over the other? SortedList implements IComparer.Compare(). Why would you also want to create a SortedList class that implements IComparable.CompareTo()? I know...
16
by: luca bertini | last post by:
Hi, i have strings which look like money values (ie 34.45) is there a way to convert them into float variables? everytime i try I get this error: "numb = float(my_line) ValueError: empty string...
32
by: andresj | last post by:
I was doing some programming in Python, and the idea came to my mind: using fractions instead of floats when doing 2/5. The problem arises when you try to represent some number, like 0.4 in a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.