Casting double by long gives wrong value.

J

johnny boy

Hello friends

I have just made this demo code.

namespace testdatatype
{
class Program
{
static void Main(string[] args)
{
double Value = long.MaxValue;
Console.WriteLine("Max value of long : " + long.MaxValue);
Console.WriteLine("Value in long of double is : " + (long)
Value);
Console.Read();
}
}
}

I am expecting that the value set to double e.g. max of long should be
printed on console but following output comes.

Max value of long : 9223372036854775807
Value in long of double is : -9223372036854775808

Also if i typecast it by ulong in Console.WriteLine() i get following
output.

Max value of long : 9223372036854775807
Value in long of double is : -9223372036854775808

Actualluy i want the exact value of long.MaxValue ?

Is there any way i can do this.

Thanks in advance
 
J

johnny boy

Wrong C# but long and double map to the underlying C datatypes so this is
a C question.
 
R

Ralf Damaschke

johnny boy wrote:

[horribly bad quoting, I *tried* to fix it]
Wrong C# but long and double map to the underlying C datatypes so this
is a C question.

Ok, I'll trust you that this is a C question. Then the argument in
the function call

Console.WriteLine("Max value of long : " + long.MaxValue);

will cause undefined behavior whenever long.MaxValue is less than 0
or greater than 21. Otherwise the output depends on the semantics of
the function Console.WriteLine which is not defined by C.

-- Ralf
 
B

Ben Pfaff

Ralf Damaschke said:
Ok, I'll trust you that this is a C question. Then the argument in
the function call

Console.WriteLine("Max value of long : " + long.MaxValue);

will cause undefined behavior whenever long.MaxValue is less than 0
or greater than 21. Otherwise the output depends on the semantics of
the function Console.WriteLine which is not defined by C.

There's no way that can be valid C, since "long" can't be the
name of a variable.
 
B

Ben Bacarisse

johnny boy said:
Wrong C# but long and double map to the underlying C datatypes so this is
a C question.

That doesn't make it a C question. This is a C question:

#include <limits.h>
#include <stdio.h>

int main(void)
{
double Value = LLONG_MAX;
printf("Max value of long long : %lld\n", LLONG_MAX);
printf("Value converted to long long is : %lld\n", (long long)Value);
return 0;
}

Why do I get:

Max value of long long : 9223372036854775807
Value converted to long long is : -9223372036854775808

when I run it? The answer is C-specific: the code exhibits undefined
behaviour. What is more, a C compiler can tell you why the answer is
not as you expect:

$ gcc -o x -std=c99 -pedantic -Wconversion x.c
x.c: In function ‘main’:
x.c:6: warning: conversion to ‘double’ alters ‘long long int’ constant value

<snip>
 
J

John Bode

Wrong C# but long and double map to the underlying C datatypes so this is
a C question.

No, it's not. It's a question of how *C#* converts from one data type
to another, and how *C#* formats data for output, not whether C# types
map to C types (they may have the same sizes, representations, and
values, but the languages don't necessarily treat them the same; for
example, C doesn't define properties like MaxValue for primitive
types).

Your original question is better suited to a newsgroup that discusses
C#.
 
R

Richard Tobin

namespace testdatatype
{
class Program
{
static void Main(string[] args)
{
double Value = long.MaxValue;
Console.WriteLine("Max value of long : " + long.MaxValue);
Console.WriteLine("Value in long of double is : " + (long)
Value);
Console.Read();
}
}
}

I am expecting that the value set to double e.g. max of long should be
printed on console but following output comes.

Max value of long : 9223372036854775807
Value in long of double is : -9223372036854775808

I take it this is C++. Here's a C version:

#include <stdio.h>
#include <limits.h>

int main(void)
{
double value = LLONG_MAX;

printf("Max long long = %lld\n", LLONG_MAX);
printf("Max long long as double = %f\n", value);
printf("Cast back to long long = %lld\n", (long long)value);

return 0;
}

I used long long because that's the 64-bit integer type on the
system I'm using. And I printed the double value itself, as well
as that value converted back to long long. I assume the read
at the end of your program is some Windows hackery.

My output is:

Max long long = 9223372036854775807
Max long long as double = 9223372036854775808.000000
Cast back to long long = 9223372036854775807

We can see that a problem has already arisen when the value is stored
in a double.

The obvious explanation is that double doesn't have the precision
to store 2^63-1 exactly; probably it has only 53 bits of precision.
The nearest representable value is is 2^63, which is what it prints.
2^63 is not representable as a long long, so when it's converted
back the behaviour is undefined; it appears that the implementation
I'm using converts doubles that are too big to LLONG_MAX.

Yours may be converting it to a sufficiently large integer type
and then truncating, resulting in the "overflow" to the most
negative value.
Actualluy i want the exact value of long.MaxValue ?

Well, the obvious answer is not to store it in a floating type
with insufficient precision...

-- Richard
 
S

Seebs

Wrong C# but long and double map to the underlying C datatypes so this is
a C question.

No, it really isn't. "Casting" is a language-specific question. If you
want to ask about C#, go ask in a C# newsgroup.

-s
 
R

Ralf Damaschke

Ben said:
There's no way that can be valid C, since "long" can't be the
name of a variable.

Can anyone confirm this never being able to be valid C with a
standard's reference? What's wrong with the following program
(apart from my syntax errors)?

/* start of program */
#include <stdio.h>

struct { long MaxValue; } myvar = { 1 };

#define long myvar

void main() {
struct { int (*WriteLine)(int); } Console = { putchar };
Console.WriteLine("Max value of long : " + long.MaxValue);
Console.WriteLine('\n');
return 0;
}

/* end of program */

Is there any constraint for defining keywords other than that in
7.1.2p4 (and this one is not violated here)?

-- Ralf
 
B

Ben Bacarisse

SaticCaster said:
LLONG_MAX is 64-bit value.

It might be longer.
See here: V113. Implicit type conversion from memsize to double type
or vice versa - http://www.viva64.com/content/PVS-Studio-help-en/V113.html

That does not appear to be a reliable site for C programmers. The
example on that pages has a typo and few clicks suggests that this is
not a rare typo. It also uses its own meanings for technical terms
when talking about C; terms which, unfortunately, have a different
technical meaning for C.
 
R

Richard Tobin

Ralf Damaschke said:
/* start of program */
#include <stdio.h>

struct { long MaxValue; } myvar = { 1 };

#define long myvar

void main() {
struct { int (*WriteLine)(int); } Console = { putchar };
Console.WriteLine("Max value of long : " + long.MaxValue);
Console.WriteLine('\n');
return 0;
}

/* end of program */

Is there any constraint for defining keywords other than that in
7.1.2p4 (and this one is not violated here)?

I'm not sure where the standard prohibits it (6.4.1 reserves keywords
"in translation phases 7 and 8" which doesn't seem to do it), but
surely an implementation can, for example, use a cast to long in
the definition of the putchar() macro, and that would be broken
by the #define above.

-- Richard
 
B

Ben Pfaff

Ralf Damaschke said:
Can anyone confirm this never being able to be valid C with a
standard's reference? What's wrong with the following program
(apart from my syntax errors)? ....
#define long myvar

As long as you are going to write obfuscated C anyway, you might
as well just do this:

#define Console nothing
#define WriteLine(arg) dummy
int main(void)
{
struct { int dummy; } nothing;
Console.WriteLine("Max value of long : " + long.MaxValue);
return 0;
}
 
R

Ralf Damaschke

Ben said:
As long as you are going to write obfuscated C anyway, you might
as well just do this:

#define Console nothing
#define WriteLine(arg) dummy
int main(void)
{
struct { int dummy; } nothing;
Console.WriteLine("Max value of long : " + long.MaxValue);
return 0;
}

Well done. So it's not only possible that the quoted code was part of a
valid C program, it even does not necessarily invoke undefined behavior
(which was the point I tried to make: the presence of UB).

-- Ralf
 
D

David Thompson

(already corrected to int)

Type mismatch; this needs .WriteLine to point to a function that takes
a char*, or a qualified char*, like puts(); the call in the next line
requires it to take an int, or some other (numeric) type to which int
converts, like putchar(). No function can actually do both of these.
Although on many machines you could defeat checking by using a K&R1
declaration and actually call the function, and probably on some of
those machines the function could reliably distinguish which argument
type was passed and handle it. As Cordy says: Got it, and, ewww.
It would be nice(r) if there were, but I'm pretty sure there isn't.
(Nor a non-constraint requirement. Since this pretty much has to occur
at compile time, there would be no point in not requiring diagnosis.)
I'm not sure where the standard prohibits it (6.4.1 reserves keywords
"in translation phases 7 and 8" which doesn't seem to do it), but
surely an implementation can, for example, use a cast to long in
the definition of the putchar() macro, and that would be broken
by the #define above.
I don't think it can, for precisely this reason. It _can_ use reserved
typenames like __secret_really_long_I_mean_it .

Aside: note that the use of putchar in the code above does NOT invoke
the function-like macro if there is one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top