Convert int to double then back to int?

  • Follow


See the following code and the output. The integer value doesn't
change. I'm wondering whether this is true everywhere or it is
specific to certain machine/OS but not others. Could somebody let me
know?

$ cat main.cpp
#include <iostream>
#include <limits>

int main() {
   //long int x= std::numeric_limits<long int>::min();
   int x= std::numeric_limits<int>::max();
   double y=x;
   int z=y;
   std::cout << x << " " << sizeof(x) << std::endl;
   std::cout << y << " " << sizeof(x) << std::endl;
   std::cout << z << " " << sizeof(x) << std::endl;
}
$ ./main.exe
2147483647 4
2.14748e+09 4
2147483647 4

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Peng 2/12/2010 4:42:50 PM

On 12 f�v, 22:42, Peng Yu <pengyu...@gmail.com> wrote:
> See the following code and the output. The integer value doesn't
> change. I'm wondering whether this is true everywhere or it is
> specific to certain machine/OS but not others. Could somebody let me
> know?
>
> $ cat main.cpp
> #include <iostream>
> #include <limits>
>
> int main() {
>    //long int x= std::numeric_limits<long int>::min();
>    int x= std::numeric_limits<int>::max();
>    double y=x;
>    int z=y;

Basically the question is whether a double can hold the maximum value
of an int. This is not guaranteed.
For double precision IEEE754 "double" and 32-bit "int", it works
without a problem, however.



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Mathias 2/12/2010 9:39:59 PM


On Feb 12, 11:42 pm, Peng Yu <pengyu...@gmail.com> wrote:
> See the following code and the output. The integer value doesn't
> change. I'm wondering whether this is true everywhere or it is
> specific to certain machine/OS but not others.
[..]

The usual implementation of floating point arithmetic is by IEEE 754,
see http://en.wikipedia.org/wiki/IEEE_754-2008. AFIR, its not an
obligation to C++ but I have never seen any different approach in C++
implementations.
Wherever the mantissa size of the double implementation equals or
exceeds the size of an int, the conversion from int to double and back
should return the original value.
This is true, for example, on 32 bit ints and IEEE double (IEEE
754-2008: binary64) - the number of bits in the mantissa (52 plus a
suppressed leading 1) guarantees preservation of int 32 bits accuracy.
However, float type, if implemented as IEEE single (IEEE 754-2008:
binary32) provides only 23+1 bits of mantissa and will cut off the
lower bits on conversion.

>    std::cout << x << " " << sizeof(x) << std::endl;
>    std::cout << y << " " << sizeof(x) << std::endl;
>    std::cout << z << " " << sizeof(x) << std::endl;}

May you meant sizeof(y) resp. sizeof(z) in the latter two rows?

best,

   MiB.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply MiB 2/12/2010 9:41:02 PM

Peng Yu wrote:
> See the following code and the output. The integer value doesn't
> change. I'm wondering whether this is true everywhere or it is
> specific to certain machine/OS but not others. Could somebody let me
> know?
> 
> $ cat main.cpp
> #include <iostream>
> #include <limits>
> 
> int main() {
>    //long int x= std::numeric_limits<long int>::min();
>    int x= std::numeric_limits<int>::max();
>    double y=x;
>    int z=y;
>    std::cout << x << " " << sizeof(x) << std::endl;
>    std::cout << y << " " << sizeof(x) << std::endl;
>    std::cout << z << " " << sizeof(x) << std::endl;
> }
> $ ./main.exe
> 2147483647 4
> 2.14748e+09 4
> 2147483647 4

It's implementation-specific.  Common floating-point implementations
cannot hold certain large integer values; specifically, they lose the
low-order digits.  Whether you can do lossless int->double->int
conversion depends on whether the platform's int can hold values in that
range.  You may be able to see the effect using long->float->long.

$ cat main.cc
#include <iostream>
#include <limits>

template<typename Int, typename Float>
void show_round_trip() {
     Int const x = std::numeric_limits<Int>::max();
     Float const y = x;
     Int const z = y;
     std::cout << sizeof(x) << ' ' << x << '\n';
     std::cout << sizeof(y) << ' ' << y << '\n';
     std::cout << sizeof(z) << ' ' << z << "\n\n";
}

int main() {
     show_round_trip<int, double>();
     show_round_trip<long, float>();
}

$ ./main
4 2147483647
8 2.14748e+09
4 2147483647

8 9223372036854775807
4 9.22337e+18
8 -9223372036854775808


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Jeff 2/13/2010 5:23:41 PM

On 12 Feb, 22:42, Peng Yu <pengyu...@gmail.com> wrote:
> See the following code and the output. The integer value doesn't
> change. I'm wondering whether this is true everywhere or it is
> specific to certain machine/OS but not others. Could somebody let me
> know?
>
> $ cat main.cpp
> #include <iostream>
> #include <limits>
>
> int main() {
> //long int x= std::numeric_limits<long int>::min();
> int x= std::numeric_limits<int>::max();
> double y=x;
> int z=y;
> std::cout << x << " " << sizeof(x) << std::endl;
> std::cout << y << " " << sizeof(x) << std::endl;

Should be sizeof(y) which will be more than 4 judging by your results.

> std::cout << z << " " << sizeof(x) << std::endl;}
>
> $ ./main.exe
> 2147483647 4
> 2.14748e+09 4
> 2147483647 4

Your doubles are bigger than your long ints but this is not
gauranteed.

It used to be that most people implemented float as 16 bits and double
as 32bits but a 16 bit float is pretty much useless and no FP units
that I know of work on it anyway so I guess that the common approach
now is for float to be 32 and double 64. It is interesting that the,
fairly new, tiny interpreted language Lua uses double as it's only
numeric type - presumably because double is now so large that it can
incorporate most practical integral values exactly on most
architectures.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Nick 2/14/2010 5:29:46 PM

Jeff Schwab wrote:
> Peng Yu wrote:
>> See the following code and the output. The integer value doesn't
>> change. I'm wondering whether this is true everywhere or it is
>> specific to certain machine/OS but not others. Could somebody let me
>> know?
>>
>> $ cat main.cpp
>> #include <iostream>
>> #include <limits>
>>
>> int main() {
>>    //long int x= std::numeric_limits<long int>::min();
>>    int x= std::numeric_limits<int>::max();
>>    double y=x;
>>    int z=y;
>>    std::cout << x << " " << sizeof(x) << std::endl;
>>    std::cout << y << " " << sizeof(x) << std::endl;
>>    std::cout << z << " " << sizeof(x) << std::endl;
>> }
>> $ ./main.exe
>> 2147483647 4
>> 2.14748e+09 4
>> 2147483647 4
> 
> It's implementation-specific.  Common floating-point implementations
> cannot hold certain large integer values; specifically, they lose the
> low-order digits.  Whether you can do lossless int->double->int
> conversion depends on whether the platform's int can hold values in that
> range.  You may be able to see the effect using long->float->long.

And if you're into digging into floating-point representations, the
macros FLT_MANT_DIG, DBL_MANT_DIG, and LDBL_MANT_DIG (from <float.h>)
tell you how many bits you have in the fraction's representation; if the
fraction is large enough to hold the bits of the integer type in
question, then you can get the round trip.

-- 
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pete 2/14/2010 7:33:13 PM

Pete Becker wrote:
> 
> And if you're into digging into floating-point representations, the
> macros FLT_MANT_DIG, DBL_MANT_DIG, and LDBL_MANT_DIG (from <float.h>)
> tell you how many bits you have in the fraction's representation; if the
> fraction is large enough to hold the bits of the integer type in
> question, then you can get the round trip.
> 

Or, if you're a purist, std::numeric_limits<double>::digits gives you 
the same information.

-- 
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pete 2/15/2010 4:45:29 PM

6 Replies
475 Views

(page loaded in 0.123 seconds)

Similiar Articles:













7/19/2012 7:10:45 PM


Reply: