473,569 Members | 3,015 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Safe conversion from floating real to integer (and vice versa)

rz0
Hi all,

This is a question about both C89 and C99 and is based on my partial
reading of the standard drafts (one from before C89 but mainly
N1124). If appropriate, please give a separate answer for each version
of the language.

Let's consider the conversion from a given floating real type to a
specific integer type.

Given a value of floating real type Tf, unknown at compile-time. What
is the safest way to convert it to a value of integer type Ti (other
than _Bool), without invoking Undefined Behavior due to out of range
error? The standard says that whenever the value would not be
representable in the converted-to type, the result would be undefined.
Yet, how do I test for valid values?

I thought there would be a macro in limits.h or float.h or maybe
stdint.h, for C99, to indicate the valid range of floating-point
values of a given type that may be converted safely from but did not
find any. I thought about testing the macros defining maximal values
of integer types but then, the test itself would invoke UB if *_MAX
were out of range of representable values, for the double type.

I did find the lrint family of functions, which only have unspecified
results when the converted value is not representable. However, it is
only part of the C99 specifications as far as I know and I would
rather have a single solution for both versions.

I am also interested in conversions from int to double, the problem is
much the same. Besides, there is no lxdbl function that would do the
opposite of lrint.

Narrowing the problem to the conversions from double to int and vice
versa, when I started learning C some years ago (by the way, I'm still
learning), I was told that the range of double was always greater than
that of int. Yet, I am unable to find in my copy of the drafts a
section where this is stated. If it is indeed the case, then the
conversion from int to double cannot cause UB and the opposite could
easily be made safe by converting INT_MAX to double and comparing to
the value which is to be converted. Could you then point out the
relevant sections for me to check by myself?

There is probably something I have missed in my reading of the drafts
or that I have not thought about, so please give advice.

Thanks in advance.
Feb 1 '06 #1
4 3364
In article <20060201155727 .5dbe4a67@local host>, rz0 <rz*@wanadoo.fr > wrote:
This is a question about both C89 and C99 Let's consider the conversion from a given floating real type to a
specific integer type. Given a value of floating real type Tf, unknown at compile-time. What
is the safest way to convert it to a value of integer type Ti (other
than _Bool), without invoking Undefined Behavior due to out of range
error?
But it is not *possible* to get a "real type Tf, unknown at compile-time".
The closest you could come would be to have some (specific) value,
take its address, convert the pointer to (void *) and then use the
pointer somehow without having passed along the history of what the
original type was. That would, however, be a fairly pointless thing
to do, as the only operation one could safely perform on the (void *)
would be to convert it to a pointer to a character and dereference
the first character.

Narrowing the problem to the conversions from double to int and vice
versa, when I started learning C some years ago (by the way, I'm still
learning), I was told that the range of double was always greater than
that of int. Yet, I am unable to find in my copy of the drafts a
section where this is stated. If it is indeed the case, then the
conversion from int to double cannot cause UB and the opposite could
easily be made safe by converting INT_MAX to double and comparing to
the value which is to be converted. Could you then point out the
relevant sections for me to check by myself?


You can compare DLB_MAX_10_EXP to the ceiling of log10 of the
number (i.e., the number of decimal digits in the integer part of the
number.)

Converting INT_MAX to double and comparing the value has the old
problem of round-off: the converted value might round upwards, and
then when converted back the result might be more than INT_MAX. And
you have the standard problems with exact comparisons of floating
point numbers.
--
I was very young in those days, but I was also rather dim.
-- Christopher Priest
Feb 1 '06 #2
rz0
On Wed, 1 Feb 2006 16:35:57 +0000 (UTC)
ro******@ibd.nr c-cnrc.gc.ca (Walter Roberson) wrote:
In article <20060201155727 .5dbe4a67@local host>, rz0 <rz*@wanadoo.fr >
wrote:
Given a value of floating real type Tf, unknown at compile-time.
What is the safest way to convert it to a value of integer type Ti
(other than _Bool), without invoking Undefined Behavior due to out
of range error?
But it is not *possible* to get a "real type Tf, unknown at
compile-time".


Well, it wasn't clear from my post but I meant the value is unknown at
compile-time. Of course, types are known. My fault.
Narrowing the problem to the conversions from double to int and
vice versa, when I started learning C some years ago (by the way,
I'm still learning), I was told that the range of double was always
greater than that of int. Yet, I am unable to find in my copy
of the drafts a section where this is stated. If it is indeed
the case, then the conversion from int to double cannot cause UB
and the opposite could easily be made safe by converting INT_MAX
to double and comparing to the value which is to be converted.
Could you then point out the relevant sections for me to check by
myself?


You can compare DLB_MAX_10_EXP to the ceiling of log10 of the
number (i.e., the number of decimal digits in the integer part of the
number.)


I see the point in doing this comparison. It won't help in finding the
greatest value representable in a int. DBL_MAX_10_EXP only gives information
about what values can be represented as a double, but not as an int so
I don't see how it relates to the problem of converting from double to int.
Please explain.

Converting INT_MAX to double and comparing the value has the old
problem of round-off: the converted value might round upwards, and
then when converted back the result might be more than INT_MAX. And
you have the standard problems with exact comparisons of floating
point numbers.


My question was not quite about that. In fact, if INT_MAX is not in
range of representable double values, the behaviour will be undefined as
specified in $6.3.1.4. That is why I am asking if it is said anywhere
in the standards that int values are all in range of double.
Feb 1 '06 #3
Please don't "justify" text. Fixed in quote.

On 2006-02-01, rz0 <rz*@wanadoo.fr > wrote:
Given a value of floating real type Tf, unknown at compile-time.
How is it unknown at compile-time?
What is the safest way to convert it to a value of integer type Ti
(other than _Bool), without invoking Undefined Behavior due to out of
range error? The standard says that whenever the value would not be
representable in the converted-to type, the result would be undefined.
Yet, how do I test for valid values?
The only way i can think of is to print it to a string with snprintf and
then read it with strtol.
I thought there would be a macro in limits.h or float.h or maybe
stdint.h, for C99, to indicate the valid range of floating-point
values of a given type that may be converted safely from but did not
find any.
You could check it against INT_MAX, but
I thought about testing the macros defining maximal values
of integer types but then, the test itself would invoke UB if *_MAX
were out of range of representable values, for the double type.


Are you sure that that invokes UB?
Feb 1 '06 #4
rz0
On 1 Feb 2006 17:15:21 GMT
Jordan Abel <ra*******@gmai l.com> wrote:
Please don't "justify" text. Fixed in quote.

On 2006-02-01, rz0 <rz*@wanadoo.fr > wrote:
Given a value of floating real type Tf, unknown at compile-time.
How is it unknown at compile-time?


I'm sorry but there is no context. This is just a thought about
conversion, not a real-life situation. I just meant that it would be a
hypothetical situation where the compiler cannot predict in any way the
value and thus the conversion has to be done at run-time with no
warning/error/diagnostic given at compile-time. I am very sorry if it
is not clear but English is not my native language and I am not used to
Usenet posting; I was just trying to provide as many useful information
as possible.
What is the safest way to convert it to a value of integer type Ti
(other than _Bool), without invoking Undefined Behavior due to out
of range error? The standard says that whenever the value would not
be representable in the converted-to type, the result would be
undefined. Yet, how do I test for valid values?
The only way i can think of is to print it to a string with snprintf
and then read it with strtol.


I have somewhat thought about it but found that it would be uneffective,
but if you say it is, then I think using such a method is fine.

But what if the type is some user-defined type then. Consider I have no
control over the type being converted from and it happens to be a type
definition. Should I convert it by hand?
I thought there would be a macro in limits.h or float.h or maybe
stdint.h, for C99, to indicate the valid range of floating-point
values of a given type that may be converted safely from but did not
find any.


You could check it against INT_MAX, but
I thought about testing the macros defining maximal values
of integer types but then, the test itself would invoke UB if *_MAX
were out of range of representable values, for the double type.


Are you sure that that invokes UB?


(ISO/IEC 9899:TC2 Committee Draft --- May 6, 2005 WG14/N1124) $6.3.1.4
says :
"When a value of integer type is converted to a real floating type, if
the value being converted can be represented exactly in the new type,
it is unchanged. If the value being converted is in the range of values
that can be represented but cannot be represented exactly, the result
is either the nearest higher or nearest lower representable value,
chosen in an implementation-defined manner. If the value being
^^^^^^^^^^^^^^^ ^^^^
converted is outside the range of values that can be represented, the
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^
behavior is undefined."
^^^^^^^^^^^^^^^ ^^^^^^^
Feb 1 '06 #5

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

Similar topics

4
11143
by: ken | last post by:
I've been looking for a solution to a string to long conversion problem that I've run into >>> x = 'e10ea210' >>> print x e10ea210 >>> y=long(x) Traceback (most recent call last): File "<pyshell#2>", line 1, in ? y=long(x)
11
2513
by: Russell E. Owen | last post by:
I realize this probably a stupid question, but...is it safe to round to the nearest integer by using int(round(val))? I suspect it is fine, but wanted to be sure that weird floating point representation on some platform might make it unsafe there (i.e. get the wrong value due to the floating point value being an approximation) and if so, is...
1
1756
by: Jimmy Seow | last post by:
Dear All, Hope somebody can help me with this. I have created a class and have got it to serialize and deserialize using XmlSerialization without any problems. I've also read the documentation on the XML attribute classes such as XmlElement and XmlRoot etc as well as XmlAttributeOverrides. However, I run into a problem if I need to...
3
8432
by: mailar | last post by:
HI, Can anyone tell me how is a multi_byte to single byte and vice versa conversion done in DB2. It would be great even if someone can tell me how Oracle does it? Oracle already has functions called to_single_byte and to_multi_byte which convert a given multi byte character to single byte and vice versa respectively. thanks in advance...
22
2300
by: junky_fellow | last post by:
Consider a function: void *test_func(void) { return ((void *)-1); } While returning, the integer -1 is converted to void *. Is this portable ?
3
17831
by: Amjad | last post by:
Hi, Are there any built-in methods in VB.NET that convert one number in one format to its equivalent in another format? For example I want to convert the number 162 (decimal) to 10100010 (binary) or to A2 (hexadecimal) and vice versa. Thanks.
27
2127
by: G Patel | last post by:
Hello, I'm having trouble with floating point problems. I'm trying to write a function that calculates the distance between two cartesian points (integer coordinates). I have the function working, but it fails on one test case. Here is my function:
17
5202
by: spooler123 | last post by:
Just a small little program. Can not figure out what am I doing wrong. #include <stdio.h> #include <limits.h> #include <float.h> int main() { double max = FLT_MAX;
8
1615
by: Roman Mashak | last post by:
Hello, this piece of code, compiled with gcc-3.4.4 (-ansi -pedantic -W -Wall), doesn't generate any warnings regarding conversion from 'double' to 'unsigned int'. Is it normal or a bug of compiler? #include <stdlib.h> #include <stdio.h> void f1(unsigned int j)
0
7703
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...
0
7619
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7930
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. ...
0
8138
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...
1
7681
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
3662
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...
0
3651
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1229
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
950
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...

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.