I'm trying to convert a float
to varbinary
, but when I try to get it back, I can't get the correct value.
For example:
select
convert(varbinary(max), convert(float, '11000000000000')) -> "0x42A402462F600000"
select
convert(varchar(max), convert(varbinary(max), convert(float, '11000000000000'))) -> "B¤F/`"
What am I doing wrong?
How can I get my float after it's been converted to binary?
The why of this question? Just to know how sql works and how manage correctly conversions data. Now, thanks @TN, i know how do it.
1条答案
按热度按时间q1qsirdb1#
Updated. See my recommended solution in Addendum 2 below.
I find it strange that SQL Server will let you save the internal float representation off as binary and will not let you reverse that operation. (Makes no sense to me). It lets you do bidirectional conversions to/from binary with nearly every other type, including the various date/time types. The only other exceptions are text/ntext, but those are obsolete pointer-to-text-storage types.
I'm guessing that you are combining this with other data in a binary string and need to be able to map everything back to their exact original values.
The only alternatives I can offer are (1) Convert to VARCHAR using the lossless conversion format -
CONVERT(VARCHAR(MAX), value, 3)
, convert from there to binary, and reverse the process to restore the original float value, or (2) Convert to the X coordinate of a Geometry::Point, from there to binary, and reverse that process (using the geometry .STX property) to restore the original float value. Both options produce binary representations several times longer than a direct conversion to binary.It seems like you will need to choose the "best bad option."
See this db<>fiddle for a demo.
ADDENDUM:
I found a potentially better, but undocumented way of performing a float to binary to float roundtrip.
After examining the binary representation of
GEOMETRY::Point(value, 0, 0)
, I found that its binary representation was0x00000000010C...0000000000000000
where the...
is the reversed binary representation of the float. Using this knowledge, it is possible to take a binary representation of the original float, construct a binary representation of a GEOMETRY::Point, convert to GEOMETRY, and extract the original float value.The following function encapsulated this technique.
This does precisely what
CONVERT(FLOAT, @Binary)
should do, if it were supported by SQL Server.See this db<>fiddle that demonstrates the prior methods and this new method. Both a directly coded conversion and a function that encapsulates that conversion are shown.
Again, I stress that this is diving into undocumented representations, but I do not believe these representations would ever change because it would break all existing databases that store geometry.
ADDENDUM2:
I found yet another method that directly deconstructs the binary into components and uses them to build up the original float value. This relies on the documented representation for IEEE 754 Double Precision values.
(This solution was adapted from an answer to this question , which used a similar calculation for single precision (SQL Server real) values.)
The equivalent conversion from Binary to Real (IEEE Single Precision) is:
Test results (double precision / SQL Server float):
Test results (single precision / SQL Server real):
See this db<>fiddle for a demo.