By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,916 Members | 1,305 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,916 IT Pros & Developers. It's quick & easy.

double or float?

P: n/a

According to the docs, floats are 32 bit and doubles are 64 bit. So
using floats should be faster than using doubles on a 32 bit processor,
and my tests confirm this. However, most of the Math methods deal with
doubles and I'm having problems with casting them back to floats.

For example:
(double)0.1f = 0.10000000149011612

I don't need the accuracy of doubles, but the speed of floats would be
benificial, but it seems I'm either going to have to write my own math
functions or just use doubles. For the record my rather basic test,
which just performed lots of multiplications and divisions, took half
the time using floats as using doubles.

Has anyone else had this problem? And can someone give me an efficient
Floor algorithm so I can write my own floating point version?

James.

Nov 15 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a

Michael Mayer wrote:

I guess I'm curious why you can't cast back to floats? Do you need the
precision or not? I have a feeling you're running into this problem:

http://www.pobox.com/~skeet/csharp/floatingpoint.html
(thanks to Jon Skeet for the article)


I don't need double precision, but the inaccuracy caused by casting can
make, for example, the Floor function give the incorrect answer:

float min=1.0f, increment=0.1f;
double result = Math.Floor(min/increment)*increment;

I'm leaving the result as a double in this example - its casting from
float to double that's causing the problem here. In theory,
min/increment will be 10.0 which is also the Floor. Multiply it by
increment and you get 1.0 again. But result comes out as
0.90000001341104507. (Try it - I swear it's true!)

Now I get that number if I put "Math.Floor(1.0f/(double)0.1f)*0.1f" into
the watch window. Even wierder, If I copy and paste
"Math.Floor(min/increment)*increment" into the watch window it gives me
the correct answer of 1.0. So I guess the compiler must be making the
conversion to double earlier than I would have expected, but either way
it's causing a problem.

I'm starting to think I should just use doubles... processors of the
future will be 64bit anyway I guess.
Nov 15 '05 #2

P: n/a
The code at the end demonstrates your problem. When casting from a float
number up to a double, you are getting some slightly skewed results. If you
divide 1/.1 in float or double you always get 10, however, casting a float
10 to a double results in some small amount of inaccuracy 9.99999985098839.
Generally you can work this off by using an error quotient or some small
decimal that gives a degree of freedom. This could be demonstrated by doing
(float fixedError = .0001f; Math.Floor((min/increment)+fixedError);) You
could also make use of the Round function instead of the floor method, or
you could roll your own floor method for floats.

using System;

public class Locality {
private static void Main(string[] args) {
float min=1.0f, increment=0.1f;
double mind=1.0D, incrementd=0.1D;

Console.WriteLine(min/increment);
Console.WriteLine(mind/incrementd);
Console.WriteLine((double) (min/increment));

Console.WriteLine(Math.Floor(min/increment));
Console.WriteLine(Math.Floor(mind/incrementd));

double result = Math.Floor(min/increment)*increment;
Console.WriteLine(result);
}
}
--
Justin Rogers
DigiTec Web Consultants, LLC.

"James Thurley" <ne********@jamesthurley.NO__SPAM.com> wrote in message
news:bi**********@titan.btinternet.com...

Michael Mayer wrote:

I guess I'm curious why you can't cast back to floats? Do you need the
precision or not? I have a feeling you're running into this problem:

http://www.pobox.com/~skeet/csharp/floatingpoint.html
(thanks to Jon Skeet for the article)


I don't need double precision, but the inaccuracy caused by casting can
make, for example, the Floor function give the incorrect answer:

float min=1.0f, increment=0.1f;
double result = Math.Floor(min/increment)*increment;

I'm leaving the result as a double in this example - its casting from
float to double that's causing the problem here. In theory,
min/increment will be 10.0 which is also the Floor. Multiply it by
increment and you get 1.0 again. But result comes out as
0.90000001341104507. (Try it - I swear it's true!)

Now I get that number if I put "Math.Floor(1.0f/(double)0.1f)*0.1f" into
the watch window. Even wierder, If I copy and paste
"Math.Floor(min/increment)*increment" into the watch window it gives me
the correct answer of 1.0. So I guess the compiler must be making the
conversion to double earlier than I would have expected, but either way
it's causing a problem.

I'm starting to think I should just use doubles... processors of the
future will be 64bit anyway I guess.

Nov 15 '05 #3

P: n/a
> I don't need double precision, but the inaccuracy caused by casting can
make, for example, the Floor function give the incorrect answer:

float min=1.0f, increment=0.1f;
double result = Math.Floor(min/increment)*increment;


There is no exact representation of 0.1 in binary.
Nov 15 '05 #4

P: n/a
Justin Rogers <Ju****@games4dotnet.com> wrote:
A floating point version of floor? Remember floor is doing nothing more
than storing an integer value so the (int) cast is perfect for this
operation.


Except they do different things for negative numbers - casting to int
rounds to 0, Floor always rounds down.

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

P: n/a

Jon Skeet wrote:
Justin Rogers <Ju****@games4dotnet.com> wrote:
A floating point version of floor? Remember floor is doing nothing more
than storing an integer value so the (int) cast is perfect for this
operation.

Except they do different things for negative numbers - casting to int
rounds to 0, Floor always rounds down.


Hmm... I guess something like this should work:

public int Floor(float val){
if(val>0.0f || val==(int)val)
return (int)val; // Positive numbers and negative whole numbers
else
return ((int)val) - 1; // Negative floating point numbers
}

Not very pretty, but should be fast!
Nov 15 '05 #6

P: n/a
> I'm starting to think I should just use doubles... processors of the
future will be 64bit anyway I guess.


the "bitness" of a CPU has nothing to do with this.
On a 32 bit CPU a float can be fetched in 1 cycle and a double in 2 cycles
On a 64 bit CPU 2 floats can be fetched in 1 cycle and a double in 1 cycle

So the net effect will be the same.
The only thing that is really a factor is how well the FP units within the
CPU are implemented.

If you are really trying to crunch numbers then look at the CPU specific
SIMD instructions available for your target CPU. Oh, and forget c# since
the runtime doesn't use them.

Oscar
Nov 15 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.