Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Interpreting Integer as Float?

Author
Message
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 30th Jun 2013 10:37
Hey there,

I'm currently working on something that would be a lot easier if there was a way to interpret integer values as floats and vice versa.
I'm not talking about usual casting (what could be done with int() or just by relying on DBPs implicit type casting) here.
As you probably know, integer and float both usually make use of 4 bytes. So internally they are both represented by 32 Bit. Now take the number 42 for instance, the binary representation of that is 00...00101010. What I need now is a way to interpret this value as if it was a float variable.

Floats are usually represented by 1 sign-bit, 8 exponent bits and 23 significant bits (Source), so 00...00101010 would - if I am not mistaken - equal a float value of +42*2^(-128). And this is basically what I want to achieve: get from a usual integer value of 42 to the respective value a float of the same internal representation would have. Is there a high-performance way (if possible without using 3rd party plugins) to achieve this effect in DBPro? I was already playing around with make memory and pointers for a while but didn't succeed.

I hope you are able to understand what I'm up to. It's not that easy to explain.. for me anyway, english not being my first language.

Cybermind
Valued Member
22
Years of Service
User Offline
Joined: 28th Nov 2002
Location: Denmark
Posted: 30th Jun 2013 11:23
Do you wan't to convert an integer to bits and then convert the bits to a float and vice versa?

The byte chrunchers are coming...
DIVIDING BY ZERO/BECAUSE WE SUCK...
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 30th Jun 2013 13:20
Well, if that's a necessary step, then yes.

Basically what I want to do is store a float value in an integer. I'm working on a scripting language type of thing which includes variables that can have different data types, and I'd like to use a DBP-integer value to store integers and floats as well that are used in the scripts for the sake of saving memory and possibly even for a better performance. I just don't know how to trick DBPro into not automatically type casting stuff...

Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 30th Jun 2013 17:20
Both data-types appear to be little-endian. An integer of value 42 uses the same bits as a float of value 42, but an integer of -1 converted to a float is 4.29497 * 10^9.

This is how I tested:


The difficulty in learning is not acquiring new knowledge but relinquishing the old.
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 30th Jun 2013 17:30 Edited at: 30th Jun 2013 17:42
Oh yes, memblocks!

Actually, I think what your code does is not the effect I was aiming at. What we see there is simply the fact that dwords are unsigned, hence -1 becomes 2^32-1 which is 4294967295 or 4.29498*10^9.
However, this actually works the way I hoped:



So using write memblock dword and memblock float on the same 4 bytes is just what I wanted.
I doubt that this is the fastest possible way, but it should suffice for now (unless somebody has a different solution, of course). Thank you.


Edit: Sadly DBPro doesn't seem to like this implementation. I wrote a small speed-test to check whether it makes sense to use this solution:



The output is 28, 55, 338, 18, 29
The first one reads a value from an array, the other 4 values are the times needed to write a value to the memblock and read it afterwards - so you could expect the last 4 values to be more or less identical, right?! - first writing and reading dwords (55ms), then writing a dword and reading a float (338ms - this is not an error, it's always much slower than the other cases), then writing and reading floats (18ms) and finally writing a float and reading a dword (29ms). I have not the slightest idea why the data types used and their order have such a tremendous effect on the speed. Can anybody run the code above and tell me the result? Maybe it's got something to do with my PC..

Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 30th Jun 2013 17:43 Edited at: 30th Jun 2013 17:48
You're welcome. I honestly have no idea how fast read/writing to memblocks is, but it's the simplest solution I could think of.

edit

When I ran your code I got:
14
27
77
16
25

The difficulty in learning is not acquiring new knowledge but relinquishing the old.
Le Verdier
13
Years of Service
User Offline
Joined: 10th Jan 2012
Location: In the mosh-pit
Posted: 30th Jun 2013 18:09 Edited at: 30th Jun 2013 18:11
There's a faster way:
Float Value = CAST DWORD TO FLOAT ( Dword Value )
Dword Value = CAST FLOAT TO DWORD ( Float Value )
These commands are part of the IanM Matrix1Dlls
http://forum.thegamecreators.com/?m=forum_view&t=85209&b=18
You should really consider to install and use this plugin
As it's add to dbpro a LOT of very useful commands...
(In particular for a scripting system...)

ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 30th Jun 2013 18:43
Indeed, that seems to do the job. I'll run a few more speed tests later today. Thanks.

Phaelax
DBPro Master
22
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 30th Jun 2013 19:14
Quote: "Float Value = CAST DWORD TO FLOAT ( Dword Value )
Dword Value = CAST FLOAT TO DWORD ( Float Value )
These commands are part of the IanM Matrix1Dlls"


What's the point of those when you can just do this?

float = myInt
integer = myFloat

DB will cast them automatically.

Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 30th Jun 2013 19:25
That won't work as required. Just consider the following:



You will find that i1 and i2 are equal whereas they won't be if you'd done what ShellfishGames was asking for.
Le Verdier
13
Years of Service
User Offline
Joined: 10th Jan 2012
Location: In the mosh-pit
Posted: 30th Jun 2013 19:28
Quote: "float = myInt
integer = myFloat

DB will cast them automatically."


It converts types
Cast will simply copy the bits without changing type!

Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 30th Jun 2013 19:29
Quote: "What's the point of those when you can just do this?"

Shellfish wants to use the same bytes to store integer/floats not just casting values between data-types.

The difficulty in learning is not acquiring new knowledge but relinquishing the old.
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 30th Jun 2013 20:19
Does DBPro use pointers? Something like the equivalent of:



In C, the compiler warns about the data types but lets it go. In DBPro if you can just point to the opposite variable types location, I imagine it'll work and be pretty speedy without complaining - assuming both data types have the same byte length.

Enjoy your day.
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 2nd Jul 2013 08:35
@Latch I don't think this is possible in DBPro (maybe with a plugin). As far as I know there are pointers, but they always point on DWORD. However, I just realized that you seemingly can use pointers to convert float values to integer, but not the other way round.




However, I just ran a speed test and got to the conclusion that those two commands from the Matrix1Utils plugin are almost exactly as fast as reading a value from an array, so I guess there's no reason not to use them.

RonsWare
14
Years of Service
User Offline
Joined: 5th Sep 2010
Location: Netherlands
Posted: 2nd Jul 2013 08:43
Maybe this helps.

http://www.thegamecreators.com/?m=codebase_view&i=5d0557322c9d4162202907c33a72befb

Cheers Ron.

Programming is learning
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 2nd Jul 2013 16:40 Edited at: 3rd Jul 2013 00:44
Quote: "//<- sadly returns 42 and not some funny float..."

As I said before, both integers and floats appear to be little-endian. Therefore the value 42 takes up the same bits in either data type so the number stays the same. Try using something like -1 instead and see what you get.

Here's what I expect the data-types look like (may not be 100% accurate):



You can see here that all numbers up to the 23rd bit are the same in both integer and float types. I may possibly have the exponents and sign the wrong way around, I'm not sure.

Attachments

Login to view attachments
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 3rd Jul 2013 13:33 Edited at: 3rd Jul 2013 13:35
OBese, when using the memblock implementation like this:

write memblock dword 1, 0, 42
print memblock float(1,0)

The program doesn't print 42 but 5.88545e-044. Remember that the exponent bits are all 0, which leads to an exponent of -128. The float representation of 42 in bits is %0 10000100 0101000....000
Because 42 is positive (hence the 0 in the beginning), the binary representation of 42 is 101010 (the first 1 always being implicit, hence the significant part starts with 01010) and the exponent should be 5 since log_2(101010 / 1.01010) = 5, but since the exponent's values 0...255 are mapped to -127...128, it has to be 5+127 = 132 = %10000100. (This is not a crazy theory of mine btw, this is what the float representation of 42 actually looks like in DBPro)

Also, integer doesn't have a sign bit. In DBPro (and as far as I know in most other languages as well), bin$(1) = %000...0001 and bin$(-1) = %111...1111. It's simply interpreted as a ring, i.e. if you add 1 to the highest positive number (which is %0111...111 or 0x7FFFFFFF or 2^31-1) you will end up with the highest negative number (which is -2^31).


Soooo what it comes down to is that you can't use pointers to convert integer to float... right?

Mage
Valued Member
18
Years of Service
User Offline
Joined: 3rd Feb 2007
Location:
Posted: 3rd Jul 2013 15:44 Edited at: 3rd Jul 2013 15:49
Quote: " It's simply interpreted as a ring, i.e. if you add 1 to the highest positive number (which is %0111...111 or 0x7FFFFFFF or 2^31-1) you will end up with the highest negative number (which is -2^31)."

I think there is a sign bit, and also the remaining bits are stored in 2's compliment. A kind of reversed/inverted binary. It makes the binary math much simpler, therefore perform better. The roll over (or number overflow) occurs and the highest number just so happens to become a binary match for the lowest negative number.

This is usually seen when people talk about the timer() which appears to be an unsigned integer. It gets too high and the integers we use to store the timer() value are negative counting upwards.

ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 3rd Jul 2013 16:17 Edited at: 3rd Jul 2013 16:20
Well, what I meant is that any number i and -i usually differ in more than one bit. It is true that the first bit of i is 1 if and only if i is negative, so in that way it could be considered a sign bit. But inverting just the first bit of any integer i will not result in -i, but in i - 2^31 if i was positive or in i + 2^31 if i was negative.

But now that we're talking about all this I realize that using bit masks you could probably improve the performance of abs() for floats. So instead of using an if-else block you simply set the sign bit to 0.
Would anybody care to run this small speed test to test it?



I get 500ms, 230ms and 360ms, although the bitmask version even relies on the slower implementation using memblocks. Interestingly even the manual if-block solution is more than twice as fast as the built in abs command... does that make any sense? (I guess it's due to the overhead caused by the function call in the case of abs, but still I kind of expected it to be faster than an if block..)

Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 3rd Jul 2013 20:08
I get similar rather puzzling results: 410/158/329.
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 4th Jul 2013 02:58
@ShellfishGames

Some abs() function calculations use

result=sqrt((number^2))

Maybe DBPro uses that. That could explain some slowness. The other possibility is that abs() may natively return an integer, but when it calculates a float, it has to recast - so this little decision in the process might be causing some lag.

Enjoy your day.

Login to post a reply

Server time is: 2025-06-22 04:49:08
Your offset time is: 2025-06-22 04:49:08