Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C/C++ pitfalls related to 64-bits (unsigned long & double)

Reply
Thread Tools

C/C++ pitfalls related to 64-bits (unsigned long & double)

 
 
Alex Vinokur
Guest
Posts: n/a
 
      02-13-2012
Hi,

unsigned long a = -1;
double b = a;
unsigned long c = b;

Model 32-bits: a == c
Model 64-bits: a != c


It is not a compiler bug for 64-bits.

Is it a design bug of C/C++ languge for 64-bits?

Alex
 
Reply With Quote
 
 
 
 
Goran
Guest
Posts: n/a
 
      02-13-2012
On Feb 13, 1:41*pm, Alex Vinokur <(E-Mail Removed)> wrote:
> Hi,
>
> unsigned long a = -1;
> double b = a;
> unsigned long c = b;
>
> Model 32-bits: * a == c
> Model 64-bits: * a != c
>
> It is not a compiler bug for 64-bits.
>
> Is it a design bug of C/C++ languge for 64-bits?


No. Your code snippet will produce "c" that equals "a" on both 32- and
64-bit systems.

If you think there is, post an example that shows the problem, e.g.:

#include <iostream>
int main()
{
unsigned long a = -1;
double b = a;
unsigned long c = b;
if (a != c)
{
std::cout << "error!";
}
}

Goran.
 
Reply With Quote
 
 
 
 
Alex Vinokur
Guest
Posts: n/a
 
      02-13-2012
On Feb 13, 2:49*pm, Leigh Johnston <(E-Mail Removed)> wrote:
> On 13/02/2012 12:41, Alex Vinokur wrote:
>
> > Hi,

>
> > unsigned long a = -1;
> > double b = a;
> > unsigned long c = b;

>
> > Model 32-bits: * a == c
> > Model 64-bits: * a != c

>
> > It is not a compiler bug for 64-bits.

>
> > Is it a design bug of C/C++ languge for 64-bits?

>
> No.
>
> a == c for both "32-bits" and "64-bits" on my compiler (VC9).
>
> /Leigh


aCC: HP C/aC++ B3910B A.06.25.01 [May 16 2010]
For 64-bits:
a = 0xffffffffffffffff
c = 0x8000000000000000

Intel(R) C++ Intel(R) 64 Compiler XE for applications running on
Intel(R) 64, Version 12.0.4.191 Build 20110427
For 64-bits:
a = 0xffffffffffffffff
c = 0





 
Reply With Quote
 
Alex Vinokur
Guest
Posts: n/a
 
      02-13-2012
On Feb 13, 2:54*pm, Goran <(E-Mail Removed)> wrote:
> On Feb 13, 1:41*pm, Alex Vinokur <(E-Mail Removed)> wrote:
>
> > Hi,

>
> > unsigned long a = -1;
> > double b = a;
> > unsigned long c = b;

>
> > Model 32-bits: * a == c
> > Model 64-bits: * a != c

>
> > It is not a compiler bug for 64-bits.

>
> > Is it a design bug of C/C++ languge for 64-bits?

>
> No. Your code snippet will produce "c" that equals "a" on both 32- and
> 64-bit systems.
>
> If you think there is, post an example that shows the problem, e.g.:
>
> #include <iostream>
> int main()
> {
> *unsigned long a = -1;
> *double b = a;
> *unsigned long c = b;
> *if (a != c)
> *{
> * std::cout << "error!";
> *}
>
> }
>
> Goran.


#include <iostream>
#include <cassert>

typedef unsigned char uchar;

#define SHOW_HEX(x) std::cerr << #x << " = " << std::hex <<
std::showbase << x << std::dec << std::endl
#define SHOW_DOUBLE(x) std::cerr << #x << " = " << x << std::endl
#define SHOW_CHAR(x) std::cerr << #x << " = " << std::hex <<
std::showbase << std::size_t(uchar(x)) << std::dec << std::endl

int main()
{
// -------------------------------------
std::cout << "Model: " << sizeof(void*) * CHAR_BIT << "-bits"<<
std::endl;
// -------------------------------------

// std::size_t a = std::size_t(-1);
// double b = a;
std::size_t a = std::numeric_limits<std::size_t>::max();
double b = a;
std::size_t c = b;
char* pa = reinterpret_cast<char*>(&a);
char* pb = reinterpret_cast<char*>(&b);
char* pc = reinterpret_cast<char*>(&c);

SHOW_HEX(a);
SHOW_DOUBLE(b);
SHOW_HEX(c);

std::cerr << std::endl;
for (std::size_t i = 0; i < (sizeof(std::size_t)/sizeof(char)); i++)
{
SHOW_CHAR(pa[i]);
}
std::cerr << std::endl;
for (std::size_t i = 0; i < (sizeof(double)/sizeof(char)); i++)
{
SHOW_CHAR(pb[i]);
}
std::cerr << std::endl;
for (std::size_t i = 0; i < (sizeof(std::size_t)/sizeof(char)); i++)
{
SHOW_CHAR(pc[i]);
}

assert (a == c);

return 0;
}
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-13-2012
On 2/13/2012 7:41 AM, Alex Vinokur wrote:
> Hi,
>
> unsigned long a = -1;
> double b = a;
> unsigned long c = b;
>
> Model 32-bits: a == c
> Model 64-bits: a != c
>
>
> It is not a compiler bug for 64-bits.
>
> Is it a design bug of C/C++ languge for 64-bits?


Whether the language design is faulty seems a matter of opinion.
However, part of the "spirit of C" is to stay fairly close to the
hardware. Since hardware that offers 64 bits of precision in the
floating-point format used for `double', some loss of precision in
`b = a' must be expected.

The language *could* have been defined to raise an exception
whenever a floating-point operation delivers an inexact result, but
that would have meant raising such exceptions for a large fraction
of all F-P calculations, perhaps many times in a single expression.
Or the language could have left the inexact conversion entirely
undefined, in which case there'd be no reason to expect `a == c'
(or even that the execution would get that far). The behavior
actually chosen (conversion yields one of the two representable
neighbors) seems fairly benign, not something I'd call a bug. But,
as I say, that's a matter of opinion.

(The language *could* have been defined to deliver exact F-P
results for all calculations, widening the representation at need.
That's the approach used on the Starship Enterprise, where Kirk
crippled the computer by asking it to calculate pi ...)

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-13-2012
Alex Vinokur <(E-Mail Removed)> writes:

Talking from the C perspective here...

> unsigned long a = -1;
> double b = a;
> unsigned long c = b;
>
> Model 32-bits: a == c
> Model 64-bits: a != c
>
> It is not a compiler bug for 64-bits.


Quite. Both outcomes are permitted.

> Is it a design bug of C/C++ languge for 64-bits?


No.

Your use of "64-bits" is a little confusing. Not all 64-bit systems
have 64 bit unsigned longs which is, I think, what you are talking
about.

On systems with 64-bit longs and standard 56-bit mantissa doubles, you
can not represent ULONG_MAX (the value of 'a' in the above code) exactly
in a double. C mandates that you get one of the two nearest
representable values, but it wont be exact. When the conversion goes
the other way the result can be undefined (if the floating point values
was rounded up to a value larger that ULONG_MAX), but, even if the
double has a value in the range of unsigned long, it will not longer
equal ULONG_MAX.

I said "no" to it being an error in the design of the language because
solving it would impose the kind of burden on implementations that C
rejects. C is designed to use native machine types wherever possible.

--
Ben.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-13-2012
On 2/13/2012 8:14 AM, Eric Sosman wrote:
> [...] Since hardware that offers 64 bits of precision in the
> floating-point format used for `double', some loss of precision in
> `b = a' must be expected.


Oh, drat. There was supposed to be an "is fairly rare" just
before the comma ...

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-13-2012
Goran <(E-Mail Removed)> writes:

> On Feb 13, 1:41*pm, Alex Vinokur <(E-Mail Removed)> wrote:
>> Hi,
>>
>> unsigned long a = -1;
>> double b = a;
>> unsigned long c = b;
>>
>> Model 32-bits: * a == c
>> Model 64-bits: * a != c
>>
>> It is not a compiler bug for 64-bits.
>>
>> Is it a design bug of C/C++ languge for 64-bits?

>
> No. Your code snippet will produce "c" that equals "a" on both 32- and
> 64-bit systems.


Not always. His (and your) use of "64-bit systems" hides that fact that
they are not all the same:

$ cat t.c
#include <stdio.h>

int main(void)
{
unsigned long a = -1;
puts(a == (unsigned long)(double)a ? "same" : "different");
}
$ gcc -o t -std=c99 -pedantic t.c
$ ./t
different

(g++ will do the same, here).

<snip>
--
Ben.
 
Reply With Quote
 
Noob
Guest
Posts: n/a
 
      02-13-2012
Alex Vinokur wrote:

> Hi,
>
> unsigned long a = -1;
> double b = a;
> unsigned long c = b;
>
> Model 32-bits: a == c
> Model 64-bits: a != c
>
>
> It is not a compiler bug for 64-bits.
>
> Is it a design bug of C/C++ languge for 64-bits?


Nicely done. You've hit all the right nails.

Remaining conspicuously vague, conflating C and C++ while cross-posting
to both groups, claiming a defect in the language, conjuring the ever
so misunderstood floating-point format, ...

You would make Kenny so proud!

If you're bored, you could read Goldberg's paper (all of it!)
http://docs.oracle.com/cd/E19957-01/..._goldberg.html
 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      02-13-2012
On Feb 13, 1:54*pm, Goran <(E-Mail Removed)> wrote:
> On Feb 13, 1:41*pm, Alex Vinokur <(E-Mail Removed)> wrote:
>
> > Hi,

>
> > unsigned long a = -1;
> > double b = a;
> > unsigned long c = b;

>
> > Model 32-bits: * a == c
> > Model 64-bits: * a != c

>
> > It is not a compiler bug for 64-bits.

>
> > Is it a design bug of C/C++ languge for 64-bits?

>
> No. Your code snippet will produce "c" that equals "a" on both 32- and
> 64-bit systems.


Here I stand ashamed. I overlook the "unsigned" part.

It's what Noob says, first and foremost. max of size_t is likely
2^64-1. That's more digits than number of significant digits "double"
can carry.

Goran.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C/C++ pitfalls related to 64-bits (unsigned long & double) Alex Vinokur C Programming 64 02-15-2012 08:00 AM
Having compilation error: no match for call to (const __gnu_cxx::hash<long long int>) (const long long int&) veryhotsausage C++ 1 07-04-2008 05:41 PM
long long and long Mathieu Dutour C Programming 4 07-24-2007 11:15 AM
unsigned long long int to long double Daniel Rudy C Programming 5 09-20-2005 02:37 AM
Assigning unsigned long to unsigned long long George Marsaglia C Programming 1 07-08-2003 05:16 PM



Advertisments