How to read a double as int64?

A

aleksa

int foo (double num)
{
if ( (int64) num == -1) return 0;

return -1;
}

I want to read a double as int64 (qword), but the compiler reads
it as double then converts it to integer, which can be a problem
since the 'num' can be a NAN.

How do I access the num as a QWORD?
 
B

BartC

aleksa said:
int foo (double num)
{
if ( (int64) num == -1) return 0;

return -1;
}

I want to read a double as int64 (qword), but the compiler reads
it as double then converts it to integer, which can be a problem
since the 'num' can be a NAN.

How do I access the num as a QWORD?

Try *(int64*)&num
 
D

Dann Corbit

int foo (double num)
{
if ( (int64) num == -1) return 0;

return -1;
}

I want to read a double as int64 (qword), but the compiler reads
it as double then converts it to integer, which can be a problem
since the 'num' can be a NAN.

How do I access the num as a QWORD?

There are a lot of problems with this idea.

For instance, if num is -1.973 do you really want to return 0?

The significant bits of the mantissa of a double will rarely (if ever)
exactly match the number of bits in a long long.

Let's reexamine the question. Exactly what problem are you really
trying to solve here. If we understand the problem clearly, then we may
be able to create a workable solution. I assume that the above stub has
nothing to do with what you are really trying to accomplish.
 
A

aleksa

There are a lot of problems with this idea.

For instance, if num is -1.973 do you really want to return 0?

No, I'm just checking for -1, read below.
The significant bits of the mantissa of a double will rarely (if ever)
exactly match the number of bits in a long long.

Let's reexamine the question.  Exactly what problem are you really
trying to solve here.  If we understand the problem clearly, then we may
be able to create a workable solution.  I assume that the above stub has
nothing to do with what you are really trying to accomplish.

Actually, it does :)

I have an array of double, with (int64) -1 as end-marker.
-1 (0xFFFFFFFFFFFFFFFF) is a NAN which I use as an end marker.
 
A

aleksa

Try *(int64*)&num

Can you please explain that expression?

(int64*) : a pointer to int64;
&num : address of num (in this case, on stack);

these two, even though I understand them individually,
I don't when are combined together.

And what does the * in front of (int64*) mean?
 
I

Ian Collins

Can you please explain that expression?

(int64*) : a pointer to int64;
&num : address of num (in this case, on stack);

these two, even though I understand them individually,
I don't when are combined together.

And what does the * in front of (int64*) mean?

The contents of the result of casting the address of num to an int64
pointer.
 
V

Vincenzo Mercuri

Can you please explain that expression?

(int64*) : a pointer to int64;

it is a cast to the type: pointer to int64.

[...]
And what does the * in front of (int64*) mean?

you are casting and dereferencing &num.


--
Non puoi insegnare qualcosa ad un uomo. You cannot teach a man anything.
Lo puoi solo aiutare -- Galileo Galilei -- You can only help him
a scoprirla dentro di sé. discover it in himself.

Vincenzo Mercuri
 
K

Keith Thompson

aleksa said:
That works, thanks.
Ugly, though..

So given a double "num", you're trying to treat its representation
as if it were a 64-bit integer. (The cast you initially tried
doesn't do this because it converts the mathematical representation.)

Note that neither "int64" nor "QWORD" is defined in standard C,
and there's no guarantee that double is 64 bits.

The *(int64*)&num solution is a bit risky; it can fail if the
alignment requirement for int64 is stricter than that for double,
or if int64 and double are not the same size. And if you're
interested in the representation, you probably want an unsigned type.
C99's <stdint.h> has uint64_t (which is not guaranteed to exist).

Here's another approach (not tested):

double num = ...;
uint64_t target;
memcpy(&target, &num, sizeof target);

This avoids any alignment problems, but it still assumes that uint64_t
exists and that it's the same size as double.
 
D

Dann Corbit

No, I'm just checking for -1, read below.


Actually, it does :)

I have an array of double, with (int64) -1 as end-marker.
-1 (0xFFFFFFFFFFFFFFFF) is a NAN which I use as an end marker.

It's also a NAN that could occur. How will you differentiate between a
NAN that occurred by calculation problem verses your magic NAN end
marker. Why is it that you do not know how long your array is, or how
many items it is populated with?
 
A

aleksa

It's also a NAN that could occur.  How will you differentiate between a
NAN that occurred by calculation problem verses your magic NAN end marker..  

Well, normal flow is to check first if it is an (int64) end marker,
then do the calculations. Of course, I hope that no normal calculation
can result in exactly-the-same NAN.
Why is it that you do not know how long your array is, or how
many items it is populated with?

It is easier (to me) just to write an end marker (especially in the
prior versions, when the num was an int) than to count and update
the count all the time (and store it somewhere). Thats how a lot
of code was written, and I don't wish to change that.
 
D

Dann Corbit

The sentinal idea works as long as the sentinal never occurs in real
data. But when it does occur there is no way to handle it properly
since it cannot be distinguished.

Hopefully your calculations can never result in that specific NAN.
 
B

BartC

Can you please explain that expression?

C can't convert double to integer (even when both are 64 bits) without
physically changing the bits (eg. from 0x3FF0000000000000 to
0x0000000000000001).

However you *can* convert a pointer to double, to pointer to integer,
without any such intervention.
(int64*) : a pointer to int64;
&num : address of num (in this case, on stack);
And what does the * in front of (int64*) mean?

&num gives a pointer to a double.

(int64*) in front converts that to a pointer to integer (but does not mess
with the bit-pattern)

The * in front of that lot dereferences the pointer to return the 'integer'
you've told it it points to.
 
E

Eric Sosman

That works, thanks.
Ugly, though..

The ugliness is a consequence of the mix-'n-match design of the
data structure: An array of type T with a sentinel of type S is an
inherently ugly arrangement. Also a fragile one: It's like marking
the end of a queue of people with a watermelon. Usually the melon
won't respond when you say "Tickets, please," but there's always a
chance somebody else decided to rest his tickets atop it for a moment.
There's also a chance that someone in the middle of the queue is
carrying a watermelon of his own ... Lots of opportunities for
confusion.
 
E

Ersek, Laszlo

[,,,] An array of type T with a sentinel of type S is an inherently ugly
arrangement. Also a fragile one: It's like marking the end of a queue
of people with a watermelon.

I'm saving these gems for the greater good of future generations, should
all usenet archives go down.

Usually the melon won't respond when you say "Tickets, please,"

Conversely, some people can't be distinguished from watermelons when
accessed through their public comm interfaces.

lacos
 
J

Jorgen Grahn

Well, normal flow is to check first if it is an (int64) end marker,
then do the calculations. Of course, I hope that no normal calculation
can result in exactly-the-same NAN.


It is easier (to me) just to write an end marker (especially in the
prior versions, when the num was an int) than to count and update
the count all the time (and store it somewhere). Thats how a lot
of code was written, and I don't wish to change that.

IMHO you should consider changing that anyway. The cast you're
discussing here is incredibly ugly.

Perhaps you can use a normal double as an end marker? Maybe you can
let anything for which n < 1e-50 is true[1] be the end marker? Your
program probably doesn't deal with more than a tiny fraction of the
full double range.

If you respond here "but this is part of a general math library; I
don't have control over what ranges people will use", then IMHO it's
even more urgent to come up with a sane solution.

/Jorgen

[1] Replace 1e-50 with something actually known to be in double's range.
I'm too lazy to look it up.
 
B

BartC

The ugliness is a consequence of the mix-'n-match design of the
data structure: An array of type T with a sentinel of type S is an
inherently ugly arrangement.

It works well with supermarket checkout tills where there is a 'next
customer' separator bar to mark the end of each customer's groceries.

The bar has to be something that can't possibly be a customer item (where
there is a shortage, it takes some ingenuity to come up, given limited
resources, with something else that the checkout operator will recognise as
an end-of-sequence item).

In this example, the sentinel is anyway just an all-1s pattern which happens
to use an integer type to pick out.
Also a fragile one: It's like marking
the end of a queue of people with a watermelon. Usually the melon
won't respond when you say "Tickets, please," but there's always a
chance somebody else decided to rest his tickets atop it for a moment.
There's also a chance that someone in the middle of the queue is
carrying a watermelon of his own ... Lots of opportunities for
confusion.

The analogy is not quite right; a real queue just won't have any more people
at the end of it and does not need a sentinel.

If a line of people really did need partitioning, a watermelon is as good a
token as any other; whatever is chosen, there's nothing to stop anyone from
carrying their own token. But in practice this just doesn't happen.
 
E

Eric Sosman

It works well with supermarket checkout tills where there is a 'next
customer' separator bar to mark the end of each customer's groceries.

The bar has to be something that can't possibly be a customer item
(where there is a shortage, it takes some ingenuity to come up, given
limited resources, with something else that the checkout operator will
recognise as an end-of-sequence item).

On my street, the trash collectors come around Monday morning
to take away the refuse you leave at the curb on Sunday evening.
There are limits to what they'll accept: No dead refrigerators, no
drums full of dubious fuming liquids, no sacks of squirming unwanted
kittens, that sort of thing -- But can you think of a perfectly
innocuous item, well within their size limits and quite clearly not
hazardous or illegal, that they *will* *not* take away?

Try discarding a rusty old trash barrel ...
The analogy is not quite right; a real queue just won't have any more
people at the end of it and does not need a sentinel.

First class passengers, watermelon, coach passengers in Group 1,
watermelon, coach passengers in Group 2, watermelon, ...
 
B

Ben Pfaff

BartC said:
It works well with supermarket checkout tills where there is a 'next
customer' separator bar to mark the end of each customer's groceries.

The bar has to be something that can't possibly be a customer item
(where there is a shortage, it takes some ingenuity to come up, given
limited resources, with something else that the checkout operator will
recognise as an end-of-sequence item).

Around here, supermarket checkout counters have a ledge along one
side stocked with two or three plastic bars (usually printed with
the supermarket's name or with advertising). When more than one
customer's items are lined up together on the counter, then each
customer uses one of these bars to separate his items from the
previous customers. That's a sentinel that the checkout clerk
and everyone in the checkout line recognizes.
 
M

Marcin Grzegorczyk

Ben said:
Around here, supermarket checkout counters have a ledge along one
side stocked with two or three plastic bars (usually printed with
the supermarket's name or with advertising). When more than one
customer's items are lined up together on the counter, then each
customer uses one of these bars to separate his items from the
previous customers. That's a sentinel that the checkout clerk
and everyone in the checkout line recognizes.

The same around here, except that a lot of
jerks^H^H^H^H^Hpeople^H^H^H^H^H^Hjerks apparently can't be bothered to
use those bars :-((
(Oh, and they're often aluminium rather than plastic.)
 

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,954
Messages
2,570,114
Members
46,702
Latest member
VernitaGow

Latest Threads

Top