Velocity Reviews > how to convert double to short ?

# how to convert double to short ?

Alan
Guest
Posts: n/a

 10-18-2003
how to convert double to short ?
for example, I want to convert

double doubleVal1 = 15000.1;
double doubleVal2 = 12000.0;
short shortVal;

shortVal = doubleVal1 - doubleVal2;

I want the result of shortVal = 3000 and store as short instead of double
value 3000.1
how can I do that?

Richard Heathfield
Guest
Posts: n/a

 10-18-2003
[Followups set to acllcc++]

Alan wrote:

> how to convert double to short ?
> for example, I want to convert
>
> double doubleVal1 = 15000.1;
> double doubleVal2 = 12000.0;
> short shortVal;
>
> shortVal = doubleVal1 - doubleVal2;
>
> I want the result of shortVal = 3000 and store as short instead of
> double value 3000.1
> how can I do that?

double doubleVal1 = 15000.1;
double doubleVal2 = 12000.0;
short shortVal;

shortVal = doubleVal1 - doubleVal2;

This is not a flippant answer.

Here is a more robust way to do the same thing:

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

int main(void)
{
double doubleVal1 = 15000.1;
double doubleVal2 = 12000.0;
short shortVal;

if(doubleVal1 - doubleVal2 < USHRT_MAX)
{
shortVal = doubleVal1 - doubleVal2;
}
else
{
printf("Can't assign to shortVal - result is too large.\n");
}
return 0;
}

--
Richard Heathfield : http://www.velocityreviews.com/forums/(E-Mail Removed)
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Mark Gordon
Guest
Posts: n/a

 10-18-2003
On Sat, 18 Oct 2003 15:46:54 +0800
"Alan" <(E-Mail Removed)> wrote:

> how to convert double to short ?
> for example, I want to convert
>
> double doubleVal1 = 15000.1;
> double doubleVal2 = 12000.0;
> short shortVal;
>
> shortVal = doubleVal1 - doubleVal2;
>
> I want the result of shortVal = 3000 and store as short instead of
> double value 3000.1
> how can I do that?

If you don't care about the direction of rounding you've just done it.
If you do care about the direction of rounding look up floor/ceil and if
using C99 round.
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.

Tim Woodall
Guest
Posts: n/a

 10-18-2003
On Sat, 18 Oct 2003 08:32:07 +0000 (UTC),
Richard Heathfield <(E-Mail Removed)> wrote:
> [Followups set to acllcc++]
>

[ignored as I don't read acllc++ and I don't have time to read
all the posts in clc as it is]
<snip>
>
> Here is a more robust way to do the same thing:
>
> #include <limits.h>
> #include <stdio.h>
>
> int main(void)
> {
> double doubleVal1 = 15000.1;
> double doubleVal2 = 12000.0;
> short shortVal;
>
> if(doubleVal1 - doubleVal2 < USHRT_MAX)
> {
> shortVal = doubleVal1 - doubleVal2;
> }
> else
> {
> printf("Can't assign to shortVal - result is too large.\n");
> }
> return 0;
> }
>

Wow, I think I have spotted two mistakes in one of Richards posts.
(Mind you the next reply to this will have Richard spotting four
mistakes in my post

Firstly, I think either the USHRT_MAX should be SHRT_MAX or
shortVal should be unsigned.

Secondly, if doubleVal1 - doubleVal2 is greater than USHRT_MAX but is
less than USHRT_MAX+1 then the if will result in the "Can't assign"
message while the assignment will be fine.

So the if needs to read:

if((unsigned short)(doubleVal1 - doubleVal2) < USHRT_MAX)

I think this is still safe if shortVal is signed giving:

if((short)(doubleVal1 - doubleVal2) < SHRT_MAX)

but I'm not going to run it on the DS9000 without confirmation first
(obviously there should also be a test for the lower bound in the
general case but I have continued the assumption that doubleVal1>doubleVal2)

Regards,

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/

Guest
Posts: n/a

 10-18-2003
Mark Gordon wrote:

>>how to convert double to short ?
>>[snip]

> If you don't care about the direction of rounding you've just done it.

For C99 at least the rounding direction of implicit conversions and
casts from floating-point types to integer types is defined as
towards-zero, i.e. truncating (6.3.1.4 clause 1). I don't have a C89
standard handy, but I suspect the same is true there.

Best regards,

Mark Gordon
Guest
Posts: n/a

 10-18-2003
On Sat, 18 Oct 2003 10:58:32 +0000 (UTC)
Tim Woodall <(E-Mail Removed)> wrote:

> On Sat, 18 Oct 2003 08:32:07 +0000 (UTC),
> Richard Heathfield <(E-Mail Removed)> wrote:
> > [Followups set to acllcc++]
> >

> [ignored as I don't read acllc++ and I don't have time to read
> all the posts in clc as it is]
> <snip>
> >
> > Here is a more robust way to do the same thing:
> >
> > #include <limits.h>
> > #include <stdio.h>
> >
> > int main(void)
> > {
> > double doubleVal1 = 15000.1;
> > double doubleVal2 = 12000.0;
> > short shortVal;
> >
> > if(doubleVal1 - doubleVal2 < USHRT_MAX)
> > {
> > shortVal = doubleVal1 - doubleVal2;
> > }
> > else
> > {
> > printf("Can't assign to shortVal - result is too large.\n");
> > }
> > return 0;
> > }
> >

> Wow, I think I have spotted two mistakes in one of Richards posts.
> (Mind you the next reply to this will have Richard spotting four
> mistakes in my post
>
> Firstly, I think either the USHRT_MAX should be SHRT_MAX or
> shortVal should be unsigned.

He also forgot to check for negative overflow.

> Secondly, if doubleVal1 - doubleVal2 is greater than USHRT_MAX but is
> less than USHRT_MAX+1 then the if will result in the "Can't assign"
> message while the assignment will be fine.

That's safe.

> So the if needs to read:
>
> if((unsigned short)(doubleVal1 - doubleVal2) < USHRT_MAX)
>
> I think this is still safe if shortVal is signed giving:
>
> if((short)(doubleVal1 - doubleVal2) < SHRT_MAX)

Definitely not I would have though since the overflow occurs when you do
the cast.

> but I'm not going to run it on the DS9000 without confirmation first
> (obviously there should also be a test for the lower bound in the
> general case but I have continued the assumption that
> doubleVal1>doubleVal2)

Never assume
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.

Mark Gordon
Guest
Posts: n/a

 10-18-2003
On Sat, 18 Oct 2003 12:59:35 +0200

> Mark Gordon wrote:
>
> >>how to convert double to short ?
> >>[snip]

>
> > If you don't care about the direction of rounding you've just done
> > it.

>
> For C99 at least the rounding direction of implicit conversions and
> casts from floating-point types to integer types is defined as
> towards-zero, i.e. truncating (6.3.1.4 clause 1). I don't have a C89
> standard handy, but I suspect the same is true there.

I thought than in C90 it was implementation defined. Based on what I
have to hand I believe that float.h provides you with FLT_ROUNDS which
gives you information about the rounding used.

However I could be wrong as my copy of K&R2 is in the office.
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.

Richard Heathfield
Guest
Posts: n/a

 10-18-2003
Tim Woodall wrote:

> On Sat, 18 Oct 2003 08:32:07 +0000 (UTC),
> Richard Heathfield <(E-Mail Removed)> wrote:
>> [Followups set to acllcc++]
>>

> [ignored as I don't read acllc++ and I don't have time to read
> all the posts in clc as it is]

Fair enough. I've reinstated clc too...

> <snip>
>>
>> if(doubleVal1 - doubleVal2 < USHRT_MAX)
>> {
>> shortVal = doubleVal1 - doubleVal2;
>> }
>> else
>> {
>> printf("Can't assign to shortVal - result is too large.\n");
>> }
>> return 0;
>> }
>>

> Wow, I think I have spotted two mistakes in one of Richards posts.
> (Mind you the next reply to this will have Richard spotting four
> mistakes in my post

Heh - I know it's not unheard of for me to do that, but this time, I'm gonna
try shutting my eyes.

>
> Firstly, I think either the USHRT_MAX should be SHRT_MAX or
> shortVal should be unsigned.

Yes, I did actually mean SHRT_MAX. I so rarely use SHRT_MAX, though, that my
fingers must have assured my brain that they knew what they were doing, and
my brain must have believed them.

> Secondly, if doubleVal1 - doubleVal2 is greater than USHRT_MAX but is
> less than USHRT_MAX+1 then the if will result in the "Can't assign"
> message while the assignment will be fine.
>
> So the if needs to read:
>
> if((unsigned short)(doubleVal1 - doubleVal2) < USHRT_MAX)

Yes, I'll buy that (suitably munged to signed short). I was hoping to avoid
the cast, though.

>
> I think this is still safe if shortVal is signed giving:
>
> if((short)(doubleVal1 - doubleVal2) < SHRT_MAX)

Yes, that looks okay to me.

> but I'm not going to run it on the DS9000 without confirmation first
> (obviously there should also be a test for the lower bound in the
> general case but I have continued the assumption that
> doubleVal1>doubleVal2)

....which I didn't even realise I was assuming! Make that three mistakes.

--
Richard Heathfield : (E-Mail Removed)
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Tim Woodall
Guest
Posts: n/a

 10-18-2003
Well I'm following up to my own post because neither of the other
replies have castigated me

On Sat, 18 Oct 2003 10:58:32 +0000 (UTC),
Tim Woodall <(E-Mail Removed)> wrote:
> On Sat, 18 Oct 2003 08:32:07 +0000 (UTC),
> Richard Heathfield <(E-Mail Removed)> wrote:

<snip>
>> double doubleVal1 = 15000.1;
>> double doubleVal2 = 12000.0;
>> short shortVal;
>>
>> if(doubleVal1 - doubleVal2 < USHRT_MAX)

<snip>
>> else
>> printf("Can't assign to shortVal - result is too large.\n");

<snip>

>>

> Wow, I think I have spotted two mistakes in one of Richards posts.
> (Mind you the next reply to this will have Richard spotting four
> mistakes in my post
>
> Firstly, I think either the USHRT_MAX should be SHRT_MAX or
> shortVal should be unsigned.
>

Well, I was ok until here.

> Secondly, if doubleVal1 - doubleVal2 is greater than USHRT_MAX but is
> less than USHRT_MAX+1 then the if will result in the "Can't assign"
> message while the assignment will be fine.
>

And ok to here as well. If only I had stopped at this point

> So the if needs to read:
>
> if((unsigned short)(doubleVal1 - doubleVal2) < USHRT_MAX)
>

Well.... I _think_ this is utter rubbish Richards code at least
worked except for a corner case.

First of all the < should be <=. But even after that the cast will
force the value to be 0..USHRT_MAX.

I'm not sure this can be solved (in clc talk). If you make the assumption
that UINT_MAX>USHRT_MAX then I think

if(doubleVal1 - doubleVal2 <= USHRT_MAX+1) would do the trick.

Maybe if(floor(doubleVal1 - doubleVal2) <= USHRT_MAX) is sufficient but I
always start getting nervous when worrying about corner cases and floating
point in the same breath .... especially if this has to work on the DS9000.

> I think this is still safe if shortVal is signed giving:
>
> if((short)(doubleVal1 - doubleVal2) < SHRT_MAX)
>

And I don't know whether this is safe but I think not. Surely there is
no difference between

short s;
double d=get_number_too_big_for_short();

s=d; /*and*/
s=(short)d;

So both are demon fodder to a DS9000.

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/

Martijn
Guest
Posts: n/a

 10-19-2003
Tim Woodall wrote:
> if((short)(doubleVal1 - doubleVal2) < SHRT_MAX)

I must admit I don't really know what I am talking about, but why is this

if ( (doubleVal1 - doubleVal2) < (double)SHRT_MAX )

I would think that in the cast to a short you may loose some information
(thinking that the largest value of short is the largest value you could
possibly fit into a the amount of bits that a short is made of - and thus
overflow may be an issue).

Thanks,

--
Martijn
http://www.sereneconcepts.nl