473,748 Members | 9,913 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

SQL Float Operation with Round() fails completely

Hi,

we found some strange behavior when operating with floats and round().
The following simplified statement reproduces the problem.

select 6.56 - round(convert(f loat, 6.56), 2)
from sysusers where name = 'public';
===========
-8.88178419

In "real world", the floats are not literals, but float fields in tables.
I could figure, that 6.56 - 6.56 will result in something like 0.00001,
but -8.88178419 is beyond my imagination.
The same statement without round results in 0.

Has anyone any clue on this?
Regards,
Peter
Jul 20 '05 #1
5 12615
Somehow you're truncating the result, and losing the E-16 (which means
*10^-16). Where are you retrieving your results? I doubt query analyzer
would do this..

select 6.56 - round(convert(f loat, 6.56), 2)

-----------------------------------------------------
-8.8817841970012 523E-16

BTW, you can add E or E0 to the end instead of convert(float, constant)

select 6.56 - round(6.56e, 2)

-----------------------------------------------------
-8.8817841970012 523E-16

6.56 is a decimal constant, and 6.56e is a float. Rounding apparently rounds
up, even when the result is further from the exact number.

select 6.56e union all
select round(6.56e,2)

-----------------------------------------------------
6.5599999999999 996
6.5600000000000 005

If your client app can't deal with floats properly, perhaps you could pass
back a varchar:

select cast(cast(6.56e as decimal(9,2)) as varchar(10))

----------
6.56

Actually, the cast as decimal shouldn't be necessary; casting as varchar
automatically rounds:

select cast(6.56e as varchar(10))

----------
6.56

Actually, it rounds a lot more than I would have thought

select cast(6.560001e as varchar(54))

------------------------------------------------------
6.56

If I want to see more digits, it seems I have to cast as decimal...

select cast(cast(6.560 00001e as decimal(9,8)) as varchar(10))

----------
6.56000001

But be careful:

select cast(cast(6.560 00001e as decimal(9,8)) as varchar(9))
Server: Msg 8115, Level 16, State 5, Line 1
Arithmetic overflow error converting numeric to data type varchar.

Return no more than 16 digits (15 decimals) for a number 0..10 and it should
be rounded properly.

select cast(cast(6.56e as decimal(18,17)) as varchar(19))

-------------------
6.5599999999999 9960

select cast(cast(6.56e as decimal(18,15)) as varchar(19))

-------------------
6.5600000000000 00

--

Incidentally, I wonder why QA sees the need to return a 53-character result
for a float. It should never need to be over 18 decimals + 1 for the decimal
point + 5 for the exponent = 24.

Hmm, BOL says this about float data type:

The Microsoft® SQL ServerT float[(n)] data type conforms to the SQL-92
standard for all values of n from 1 to 53. The synonym for double precision
is float(53).

So it's treating the precision (53) as the the width... weird.

---------------------------------------

"Peter Scheurer" <sc******@gmx.c om> wrote in message
news:2b******** *************** ***@posting.goo gle.com...
Hi,

we found some strange behavior when operating with floats and round().
The following simplified statement reproduces the problem.

select 6.56 - round(convert(f loat, 6.56), 2)
from sysusers where name = 'public';
===========
-8.88178419

In "real world", the floats are not literals, but float fields in tables.
I could figure, that 6.56 - 6.56 will result in something like 0.00001,
but -8.88178419 is beyond my imagination.
The same statement without round results in 0.

Has anyone any clue on this?
Regards,
Peter
Jul 20 '05 #2

"Peter Scheurer" <sc******@gmx.c om> wrote in message
news:2b******** *************** ***@posting.goo gle.com...
Hi,

we found some strange behavior when operating with floats and round().
The following simplified statement reproduces the problem.

select 6.56 - round(convert(f loat, 6.56), 2)
from sysusers where name = 'public';
===========
-8.88178419

In "real world", the floats are not literals, but float fields in tables.
I could figure, that 6.56 - 6.56 will result in something like 0.00001,
but -8.88178419 is beyond my imagination.
The same statement without round results in 0.

Has anyone any clue on this?
Regards,
Peter


The result of the query above is this (on my system):

-8.8817841970012 523E-16

Note the E-16 at the end - that's the number before the E multiplied by 10
to the power of minus 16, which is a very small number indeed. Since float
calculations are not precise, a very small difference is not unusual.
Compare the result of this query:

select cast(1.01 as float)-cast(1.0 as float)

1.0000000000000 009E-2

This is roughly 1E-2, ie. 0.01.

Simon
Jul 20 '05 #3
I'd like to add that decimal calculations aren't precise either, if you are
calculating with numbers that can't be represented 100% accurately in a
decimal form, eg 1.0/3.0 or 1.0/7.0. Binary calculations are precise on
numbers that are representable accurately in binary in the number of bits
provided in the mantissa of the FLOAT (53 bits) or REAL (24 bits), eg. any
number which can be represented as SUM(POWER(2,x)) where x is a range of
integers such that MAX(x)-MIN(x) <= 52, for FLOAT. Decimals are often not
accurately represented in binary (FLOAT/REAL), because 1/5 is not accurately
representable in binary. The Decimal datatypes change the exponent to a
power of 10, and make the mantissa an integer of 4, 8, 12 or 16 bytes, so
that all decimal numbers of up to 38 digits can be accurately represented.

SELECT 1.-2./3.-1./3.

-----------
.000001

(wow, only 6 decimals by default for a decimal?)

SELECT 1 - 2/3e0 - 1/3e0

-----------------------------------------------------
5.5511151231257 827E-17
SELECT 1.0/7.0*7.0

-------------
.9999990

--SELECT 1.0/7.0*7.0

declare @decimals int
declare @sql varchar(80)
set @decimals=0
while @decimals<37
begin
set @sql='print cast(1.'+replic ate('0',@decima ls)+' as varbinary)'
exec(@sql)
set @decimals = @decimals + 1
end

Some output:
0x0100000101000 000 -- 1. is represented as 1 * 10^(1-1)
0x020100010A000 000 -- 1.0 is 10 (0x0A) * 10^(2-1)
0x0302000164000 000 -- 1.00 is 100 (0x64) * 10^(3-1)... etc
....
0x0B0A000100E40 B5402000000
....
0x1514000100001 0632D5EC76B0500 0000
....
0x1E1D000100000 0A0CA17726DAE0F 1E4301000000
....
0x2524000100000 000109F4BB31507 C97BCE97C000
"Simon Hayes" <sq*@hayes.ch > wrote in message
news:40******** @news.bluewin.c h...

[...] Since float
calculations are not precise, a very small difference is not unusual.
Compare the result of this query:

select cast(1.01 as float)-cast(1.0 as float)

1.0000000000000 009E-2

This is roughly 1E-2, ie. 0.01.

Simon

Jul 20 '05 #4
Thank you Simon and Aaron,

you were both right:
I tried the statement with query analyzer and I got the correct and
complete result.
It is sqltalk - a tool from Centura Developer, that does the wrong job
when converting floats for viewing in the result window.

Thank you for helping me.
Peter

The result of the query above is this (on my system):

-8.8817841970012 523E-16

Note the E-16 at the end - that's the number before the E multiplied by 10
to the power of minus 16, which is a very small number indeed. Since float
calculations are not precise, a very small difference is not unusual.
Compare the result of this query:

select cast(1.01 as float)-cast(1.0 as float)

1.0000000000000 009E-2

This is roughly 1E-2, ie. 0.01.

Simon

Jul 20 '05 #5
Thank you Simon and Aaron,

you were both right:
I tried the statement with query analyzer and I got the correct and
complete result.
It is sqltalk - a tool from Centura Developer, that does the wrong job
when converting floats for viewing in the result window.

Thank you for helping me.
Peter

The result of the query above is this (on my system):

-8.8817841970012 523E-16

Note the E-16 at the end - that's the number before the E multiplied by 10
to the power of minus 16, which is a very small number indeed. Since float
calculations are not precise, a very small difference is not unusual.
Compare the result of this query:

select cast(1.01 as float)-cast(1.0 as float)

1.0000000000000 009E-2

This is roughly 1E-2, ie. 0.01.

Simon

Jul 20 '05 #6

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

Similar topics

2
2011
by: j vickroy | last post by:
Howdy, I do not understand the following behavior for: PythonWin 2.3.2 (#49, Oct 2 2003, 20:02:00) on win32. >>> >>> float('0.0') 0.0 >>> row = ('0.0', '1.0', None)
9
1993
by: Vineet Jain | last post by:
int('2.1') does not work while int(float('2.1')) does. If int can covert a float object then there is no reason why a float string should not be converted too. When I do int('2.1') I get the following error: >>> a = int('2.0') Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: invalid literal for int(): 2.0
9
2336
by: Marc Schellens | last post by:
My compiler warns about assignment to int form float/double. Will it nevertheless do what I expect? Are there caveeats/pits? (Apart from the range and the precision of course) What would be the best way to do it? thanks, marc
5
1877
by: Pat | last post by:
Give two double-typed variable X and Y. If (X==Y) is true, then how about the following results: (float(X) > float(Y))? (float(X) < float(Y))? (float(X) >= float(Y))? ( X > float(Y) )? ( X < float(Y) )?
9
1703
by: Domel | last post by:
1 Jak zaokr±glić float'a tak żeby jeżeli czę¶ć dziesiętna była większa lub równa od 0.5 to był on zaokr±glany w górę, jeżeli mniejsza to w dół np 1.6 po zaokr 2.0 1.2 po zaokr 1 prosiłbym o ile to możliwe o jakie¶ sposoby bez doł±czania bibliotek, przy użyciu jakich¶ operacji 2. dla czego jeżeli wykonuję poniższ± operację
6
2301
by: Dave win | last post by:
Hi all: I'm confused with the expression "(float *())". Book says that this is a cast. But, I have no idea of this expr. why could this expr ignore the variable??? Thanx!!!
3
34920
by: Terje Barman | last post by:
Hi! I have sumarized float values and I'd like to round the sum to a certain precision. Say I have 1.234 and want it rounded to 1.23. Which method can I use? Terje
19
4691
by: morc | last post by:
hey, I have float values that look something like this when they are printed: 6.0E-4 7.0E-4 I don't want them to be like this I want them to be normalized with 4 decimal places.
116
35941
by: Dilip | last post by:
Recently in our code, I ran into a situation where were stuffing a float inside a double. The precision was extended automatically because of that. To make a long story short, this caused problems elsewhere in another part of the system where that figure was used for some calculation and some eventual truncation led to the system going haywire. So my question is, given this code: int main() { float f = 59.89F;
0
8987
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9534
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9366
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9241
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6793
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6073
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4597
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3303
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2211
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.