448,581 Members | 993 Online
Need help? Post your question and get tips & solutions from a community of 448,581 IT Pros & Developers. It's quick & easy.

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

4 Replies

 P: n/a In article <20060201155727.5dbe4a67@localhost>, rz0 wrote:This is a question about both C89 and C99 Let's consider the conversion from a given floating real type to aspecific integer type. Given a value of floating real type Tf, unknown at compile-time. Whatis the safest way to convert it to a value of integer type Ti (otherthan _Bool), without invoking Undefined Behavior due to out of rangeerror? 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 viceversa, when I started learning C some years ago (by the way, I'm stilllearning), I was told that the range of double was always greater thanthat of int. Yet, I am unable to find in my copy of the drafts asection where this is stated. If it is indeed the case, then theconversion from int to double cannot cause UB and the opposite couldeasily be made safe by converting INT_MAX to double and comparing tothe value which is to be converted. Could you then point out therelevant 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

 P: n/a On Wed, 1 Feb 2006 16:35:57 +0000 (UTC) ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote: In article <20060201155727.5dbe4a67@localhost>, rz0 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 outof 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 andvice 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 alwaysgreater than that of int. Yet, I am unable to find in my copyof the drafts a section where this is stated. If it is indeedthe case, then the conversion from int to double cannot cause UBand the opposite could easily be made safe by converting INT_MAXto double and comparing to the value which is to be converted.Could you then point out the relevant sections for me to check bymyself? 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

 P: n/a Please don't "justify" text. Fixed in quote. On 2006-02-01, rz0 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

 P: n/a On 1 Feb 2006 17:15:21 GMT Jordan Abel wrote: Please don't "justify" text. Fixed in quote. On 2006-02-01, rz0 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