I need to write function like double_to_int(double val, int *err)
which
would covert double val to integer when it's possible; otherwise report an error (NAN/INFs/OUT_OF_RANGE).
so pseudo code implementation would look like:
if isnan(val):
err = ERR_NAN
return 0
if val < MAX_INT:
err = ERR_MINUS_INF
return MIN_INT
if ...
return (int)val
There are at least two similar questions on SO:
in this answer it's solved in enough clean way, though it's C++ solution - in C we do not have portable digits for signed int.
In this answer, it's explained why we cannot just check (val > INT_MAX || val < INT_MIN)
.
So the only possible clean way i see is to use floating point environment, but it's stated as implementation-defined feature.
So my question: is there any way to implement double_to_int
function in cross-platform way (basing only on C standard, even not considering
target platforms to support IEEE-754).?
We can convert double to int in java using typecasting. To convert double data type into int, we need to perform typecasting. Typecasting in java is performed through typecast operator (datatype).
To convert a Double value to an integer value, use the Convert. ToInt32() method. Int32 represents a 32-bit signed integer.
You can't simply convert a double to an int in C++ because the word convert doesn't have a specific meaning.
The answer to "Can a conversation from double to int be written in portable C" is clearly "yes".
For example, you could sprintf the floating value to a string, do string-based inspection (i.e. by string-based comparison to max and min values you also sprintf’d), validation, rounding, etc and then sscanf the known-valid string for the final value.
In effect, you’d be moving toward an intermediate representation that’s (a) portable and (b) convenient. C strings are fine at portability, but not so convenient. If you can use external libraries, there are several that are convenient, but whose portability should be confirmed.
For example (which omits rounding):
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <string.h>
int convert(double inVal) {
// basic range check - does anybody have an integer format with more than 300 bits?
if (fabs(inVal) > 1.0E100) {
printf("well out of range");
return 1;
}
// load string buffer with input
char buf[110];
sprintf(buf, "%0105.0f", inVal);
// do range check on strings
if (inVal < 0) {
char minVal[110];
sprintf(minVal, "%0105d", INT_MIN);
if (strcmp(buf, minVal) > 0) {
printf("too small input: %f\n", inVal);
return -1; // needs better error signify
}
} else {
char maxVal[110];
sprintf(maxVal, "%0105d", INT_MAX);
if (strcmp(maxVal, buf) < 0) {
printf("too large input: %f\n", inVal);
return -1; // needs better error signify
}
}
// do final conversion
int result;
sscanf(buf, "%d", &result);
printf("input: %f result: %d\n", inVal, result); // diagnostic
return result;
}
int main()
{
// test values
convert( 0.);
convert( -123.5);
convert( 123.5);
convert( ((double)INT_MIN)-1);
convert( ((double)INT_MIN));
convert( ((double)INT_MIN)+1);
convert( 2.0*((double)INT_MIN));
convert( ((double)INT_MIN)/2);
convert( ((double)INT_MAX)-1);
convert( ((double)INT_MAX));
convert( ((double)INT_MAX)+1);
convert( 2.0*((double)INT_MAX));
convert( ((double)INT_MAX)/2);
return 0;
}
Which produces the expected conversions (see test cases at end above):
% gcc test.c ; ./a.out
input: 0.000000 result: 0
input: -123.500000 result: -124
input: 123.500000 result: 124
too small input: -2147483649.000000
input: -2147483648.000000 result: -2147483648
input: -2147483647.000000 result: -2147483647
too small input: -4294967296.000000
input: -1073741824.000000 result: -1073741824
input: 2147483646.000000 result: 2147483646
input: 2147483647.000000 result: 2147483647
too large input: 2147483648.000000
too large input: 4294967294.000000
input: 1073741823.500000 result: 1073741824
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With