GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 09-May-2007, 11:59
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 469
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

combining localtime() members into a single long long


Hi,
I am trying to create one long integer to use as a timestamp for user input enties rather that store several values which can be obtained from localtime().
ie: 200705091335 which would be handy for sorting and only use 4 bytes.

Things were moving along well until I ran into a problem with the long integer.
I think it's my printf specifiers, but not sure, when I go over limit I get 20 place! (see below)
I can't figure what else I could change there.
The longest I could think of doing was a printf( %llu ) as below.

Of course you may also know a better way of trying to get that int!
Heres what I'm trying:
CPP / C++ / C Code:
/* timestamp.c */

#include <stdio.h>
#include <time.h>
void sleep(time_t seconds);  //have to include ptype in dmc compiler...

int main()
{  
  int i = 0;
  unsigned long long timestamp;
  char time_stamp[20];   // unused at this time
  time_t tstamp;
  struct tm *Tp;

  while(i < 5) {
    tstamp = time(NULL);
    Tp = localtime(&tstamp);
    printf("time_stamp: %d %02d %02d %02d %02d %02d \n", (1900 + Tp->tm_year), (Tp->tm_mon + 1), Tp->tm_mday, Tp->tm_hour, Tp->tm_min, Tp->tm_sec );
    sleep(3);
    i++;
  }
  timestamp = (1900 + Tp->tm_year) * 1000000;  //max 6- 0's hmmm...
  printf("timestamp = %llu \n", timestamp);
  printf("sizeof long %d \n", sizeof(long));
  printf("sizeof long long %d \n", sizeof(long long));
}
/*  
    output with 6- 0's:
time_stamp: 2007 05 09 13 02 52
timestamp = 2007000000
sizeof long 4
sizeof long long 8

    output with 7- 0's:
time_stamp: 2007 05 09 13 01 09
timestamp = 18446744072304715136
sizeof long 4
sizeof long long 8
*/
Thanks, Howard
  #2  
Old 09-May-2007, 12:16
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 469
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: combining localtime() members into a single long long


awww man,,, I only had to cast it correctly!....
CPP / C++ / C Code:
//  timestamp = (1900 + Tp->tm_year) * 1000000;  //max 6- 0's hmmm...

  timestamp = ((long long)(1900 + Tp->tm_year)) * 10000000000;
  printf("timestamp = %llu \n", timestamp);

/*   output  
time_stamp: 2007 05 09 14 04 45
timestamp = 20070000000000
sizeof long 4
sizeof long long 8
 */
Back on track now.... Sorry
  #3  
Old 09-May-2007, 19:55
TurboPT's Avatar
TurboPT TurboPT is offline
Regular Member
 
Join Date: Feb 2006
Location: Atlanta, GA
Posts: 958
TurboPT is a jewel in the roughTurboPT is a jewel in the roughTurboPT is a jewel in the rough

Re: combining localtime() members into a single long long


Out of curiosity, what do you use to compile?

I get 'forbidden' when using a back-2-back long long, except in one environment, see below:

VC++ 6:
Quote:
error C2632: 'long' followed by 'long' is illegal
Cygwin:
Quote:
error: ISO C++ does not support `long long'
(I had to turn on -pedantic to see this error)
VC++ Express did not complain, and the help claims:
Code:
Type | Bytes | Other-Name ======================================= long long | 8 | none (but equivalent to __int64)
Just to see if Express would complain about a long long long, it did:
Quote:
error C2632: '__int64' followed by 'long' is illegal
(so the help info didn't lie about the equivalence of the first two longs)
__________________
Use the force...read the source!!
WYCIWYG -- what you code is what you get!
  #4  
Old 09-May-2007, 22:09
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,702
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: combining localtime() members into a single long long


Quote:
Originally Posted by TurboPT
I get 'forbidden' when using a back-2-back long long, except in one environment, see below:

VC++ 6:

There are proprietary data types for 64-bit integers. Look in the documentation. Printing them out also requires proprietary format specifiers. I am not sitting at a Windows machine so I can't check it out exactly, but I remember a thread a long time ago where I enumerated and gave examples of them. I think the data types were __int64, and the format to print them was "%IA64", but I could be mis-remembering them. Look in compiler documentation and/or msdn for details.

Quote:
Originally Posted by TurboPT
Cygwin:
Actually, I got warnings, not errors with gcc 3.4.6 and 4.1.1.

With recent GNU compilers, use a command-line switch of '-std=c99', and they will cheerfully accept long long (even with -pedantic) and it will cheerfully print with "%ll" format, as specified in the C99 standard. No pesky warnings.
Quote:
Originally Posted by TurboPT
Just to see if Express would complain about a long long long, it did:
See my above comments on VC++ version 6; I'm guessing they are the same here.

Additional information:

Old Borland compilers that I used (before 2006) had _int64, I think, instead of the Microsoft __int64. I don't remember offhand what the format specifer was. Recent Borland compilers have "long long" and also have <stdint.h>, where it does typedefs such as uint64_t for 64 bit integers (it's the same as long long).

GNU gcc/g++ also have had the C99 <stdint.h> data types for several revisions now (since 3.4.something at least). uint32_t specifies a 32-bit unsigned int; uint64_t specifies a 64-bit unsigned, etc.

In my programs these days, where size is important, I use things like uint64_t for declarations. If the compiler doesn't have <stdint.h>, then I make my own typedefs to int64_t using whatever proprietary types are native to that compiler.

That way, porting the program to other compilers and other systems involves at most a few typedefs at the beginning. The c99 header <inttypes.h> also has macros defined to print them out. They take a little getting used to, but could help portability also.

If you are a regular user of gcc/g++, I suggest you read up on <stdint.h> and <inttypes.h> (Actually <inttypes.h> includes <stdint.h>)




Regards,

Dave

Footnote: This is the C forum, but I mentioned C++ a couple of times. I should also mention that "long long", <stdint.h> and <inttypes.h> are part of the C standard (the C99 Standard, that is), not C++. C compilers that I use for desktop applications are also C++ compilers, and I note that GNU compilers and current versions of Borland bcc32 also compile C++ programs with "long long" and <stdint.h> just dandy, although the "-pedantic" flag with g++ gives warnings. It's not an issue with the modest embedded applications that I have participated in, since they are C.
  #5  
Old 09-May-2007, 23:24
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 469
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: combining localtime() members into a single long long


Interesting discussion.
In windows 98 I am using the Digital Mars 'dmc' C/C++ Compiler Version 8.49.
I just got back from linux gcc 3.??? I forget... redhat 9 era.

I don't get any warnings using either compiler.
I see dmc has both stdint.h and inttypes.h and I see the:
typedef unsigned long long uint64_t;

I'll have to give that a try and remember for the future!
btw , here's how I finished that experiment. Pretty fun! :
CPP / C++ / C Code:
#include <time.h>
void sleep(time_t seconds);  //have to include ptype in dmc compiler...

int main()
{
  int i = 0;
  unsigned long long timestamp, adjustyr = 2*10e12;
  time_t tstamp;
  struct tm *Tp;

  while(i < 5) {
    tstamp = time(NULL);
    Tp = localtime(&tstamp);
    printf("  time_stamp: %d %02d %02d %02d %02d %02d \n", (1900 + Tp->tm_year), (Tp->tm_mon + 1), Tp->tm_mday, Tp->tm_hour, Tp->tm_min, Tp->tm_sec );
 
  //timestamp = (1900 + Tp->tm_year) * 1000000;  //max 6- 0's hmmm...
  //timestamp = ((long)(1900 + Tp->tm_year)) * 10000000000;
  timestamp =  ((long long)(Tp->tm_year + 1900)) * 10e9;   // for 2007
  //timestamp =  ((long long)(Tp->tm_year - 100))  * 10e9;   // for 07
  timestamp = timestamp + ((Tp->tm_mon  + 1)     * 10e7);
  timestamp = timestamp + ((Tp->tm_mday)         * 10e5);
  timestamp = timestamp + ((Tp->tm_hour)         * 10e3);
  timestamp = timestamp + ((Tp->tm_min)          * 10e1);
  timestamp = timestamp +  (Tp->tm_sec);

    // these just adjust the value to be printed
  printf("1 timestamp = %012llu \n", timestamp);  //prints full 2007
  printf("2 timestamp = %012llu \n", timestamp - 20000000000000);
  printf("3 timestamp = %012llu \n", timestamp - (long long)(2 * 10e12));
  printf("4 timestamp = %012llu \n", timestamp - adjustyr);

    // the next one actually changes the value then prints
  timestamp = timestamp - (2 * 10e12) ;
  printf("5 timestamp = %012llu \n\n",  timestamp );

  sleep(3);
    i++;
  }
  printf("sizeof long %d \n", sizeof(long));
  printf("sizeof long long %d \n", sizeof(long long));
  return 1;
}

/* output 
 . . . . . (last loop) . . . .
  time_stamp: 2007 05 10 01 42 35
1 timestamp = 20070510014235
2 timestamp = 070510014235
3 timestamp = 070510014235
4 timestamp = 070510014235
5 timestamp = 070510014235

sizeof long 4
sizeof long long 8  */
++Howard;
  #6  
Old 10-May-2007, 07:50
TurboPT's Avatar
TurboPT TurboPT is offline
Regular Member
 
Join Date: Feb 2006
Location: Atlanta, GA
Posts: 958
TurboPT is a jewel in the roughTurboPT is a jewel in the roughTurboPT is a jewel in the rough

Re: combining localtime() members into a single long long


More info:

In that cygwin test I tried, was actually with g++ 3.4.4 (not realizing the forum I was under, duh), with the -pedantic gave that message. Without -pedantic, there were no errors/warnings.

Thanks for the info Dave!
-PT
__________________
Use the force...read the source!!
WYCIWYG -- what you code is what you get!
  #7  
Old 10-May-2007, 08:34
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,702
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: combining localtime() members into a single long long


Quote:
Originally Posted by Howard_L
I Pretty fun
That's my experience: This stuff is kind of fun when it works!

Here's something else to explore. When evaluating polynomials, knowledgeable programmers use a method sometimes called Horner's nesting scheme. Rather than describing it in words, I'll give an example using your program. (With polynomials whose coefficients are in an array, the program is a really simple loop).

CPP / C++ / C Code:
        timestamp = Tp->tm_year + 1900;
        printf("a: Timestamp = %llu\n", timestamp);

        timestamp = 100 * timestamp + (Tp->tm_mon + 1);
        printf("b: Timestamp = %llu\n", timestamp);

        timestamp = 100 * timestamp + (Tp->tm_mday);
        printf("c: Timestamp = %llu\n", timestamp);

        timestamp = 100 * timestamp + (Tp->tm_hour);
        printf("d: Timestamp = %llu\n", timestamp);

        timestamp = 100 * timestamp + (Tp->tm_min);
        printf("e: Timestamp = %llu\n", timestamp);

        timestamp = 100 * timestamp + (Tp->tm_sec);
        printf("f: Timestamp = %llu\n", timestamp);

        printf("From Horner's nesting scheme: timestamp = %llu\n", timestamp);

By printing out each step, you can see how the previous value is shifted left two decimal digits before adding the next one.
Code:
time_stamp: 2007 05 10 07 35 08 a: Timestamp: 2007 b: Timestamp: 200705 c: Timestamp: 20070510 d: Timestamp: 2007051007 e: Timestamp: 200705100735 f: Timestamp: 20070510073508 From Horner's nesting scheme: timestamp = 20070510073508

What's the advantage (other than the "fun" part and the elegance of a consistent sequence of similar operations)? Well, suppose you decide you don't want seconds. Then just leave off the last operation; none of the previous program statements have to be changed. Just a thought.

Regards,

Dave
  #8  
Old 11-May-2007, 00:10
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 469
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: combining localtime() members into a single long long


...and they said there would be no math... Wow... after looking at a few googled pages on polynomials, I remember why I struggled so much with algebraI. That's as far as I got! I choked and graduated 12th in '73 with a general applied math course.... Nevertheless, I've been trying to get an idea of what you're trying to illustrate.

Are you saying to place those tm values into an array and loop through the array?
Then again I'm thinking of 'nested' as being something like this:
CPP / C++ / C Code:
#include <stdio.h>
#include <time.h>
#define ULL (unsigned long long)

int main()
{
  int i, j = 0;
  int T[6];
  unsigned long long timestamp;
  time_t tstamp;
  struct tm *Tp;


  while(j < 10) {   // this loop is just to see how fast this stuff is!
	int *Tptr = T;
    tstamp = time(NULL);
    Tp = localtime(&tstamp);

    *Tptr++ = Tp->tm_year + 1900;
    *Tptr++ = Tp->tm_mon + 1;
    *Tptr++ = Tp->tm_mday;
    *Tptr++ = Tp->tm_hour;
    *Tptr++ = Tp->tm_min;
    *Tptr++ = Tp->tm_sec;

    printf("1- %d%02d%02d%02d%02d%02d \n", T[0], T[1], T[2], T[3], T[4], T[5]);

    printf("2- ");
    for(i=0; i < 6; i++) {   // adjust loop to loose sec, min, hour, etc
      printf("%02d", T[i]);
    }
    putchar(0xa);

    timestamp = (((((ULL(T[0])*100+T[1])*100+T[2])*100+T[3])*100+T[4])*100+T[5]);
       // note the cast down in the nest is contageous throughout the rest!
    printf("3- %llu \n", timestamp);

    timestamp = 0;
    for(i=0; i < 6; i++) {
      timestamp = timestamp*100+T[i];
    }
    printf("4- %llu \n\n", timestamp);

    j++;
  }
  return 1;
}
/* output: (at least 10 times in one second)
1- 20070511021409
2- 20070511021409
3- 20070511021409
4- 20070511021409
/* 
Nifty! , I'm gonna have to think about that one...
But don't ask me to put it into a poynomial and reduce to lowest terms
Thanks Dave! Every day something new.
++Howard;
  #9  
Old 11-May-2007, 01:12
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,702
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: combining localtime() members into a single long long


Quote:
Originally Posted by Howard_L
Are you saying to place those tm values into an array and loop through the array?
I didn't really have that in mind for this program although it certainly works---as you showed. I just wanted to give a little context.

Experience in one area can be helpful in solving problems in other areas, and if you think about it, the positional notation of our number systems is an example of a polynomial in powers of 10. Your example used powers of 100 to place the individual elements of the struct into a single number, and the math is exactly the same as evaluating a polynomial.

Suppose the four coefficients of a third degree polynomial in x are in an array: a[0], a[1], a[2], a[3], where

a[0] is the constant term (coefficient of x to the zero power)
a[1] is the coefficient of x to the first power
a[2] is the coefficient of x to the second power
a[3] is the coefficient of x to the third power

Let n = 4 (the number of coefficients)

Naive programmers would probably do something like the following to evaluate the polynomial:

CPP / C++ / C Code:
    sum = 0;
    for (i = 0; i < n; i++) {
        sum = sum + a[i] * pow(x, i);
    }

or, equivalently

CPP / C++ / C Code:
    sum = 0;
    for (i = n-1; i >= 0; i--) {
        sum = sum + a[i] * pow(x, i);
    }

Astute programmers, would more likely use the nesting scheme:

CPP / C++ / C Code:
    sum = 0;
    for (i = n-1; i >= 0; i--) {
        sum = (sum * x) + a[i];
    }

Or even more efficiently
CPP / C++ / C Code:
    sum = a[n-1];
    for (i = n-2; i >= 0; i--) {
        sum = (sum * x) + a[i];
    }


That's known as 'using your head'. (It's also known as Horner's nesting scheme.) Why go through the expense of calling a mathematical function for each power of x as you go through the loop? You just start with the most significant and then each time through the loop you take the previous value and "shift left" by multiplying by the base and then add the new one.

This is exactly what I showed for my take on your datecode calculation (except I didn't bother to put them into an array and make a loop).

In numerical analysis, sometimes problems have to evaluate polynomials millions of times (or more). The waste of using the power function is intolerable. Furthermore, what if the polynomials are for integer powers? The library funciton pow() is a floating point function (you could write your own integer power function, of course). The idea of needlessly calling a floating point function, and incurring the expense of converting arguments and return values back and forth between ints and doubles, not to mention the possibility of introducing roundoff error, simply isn't acceptable. (Not to me, at least.)

In your loop, you started with the most significant part in the zeroth element of the array, so the loop started at zero. Actually I like your way better for some cases, but mathematicians like the other way around. The important point is that the math is exactly the same for your datecode as the polynomial evaluation.

Now, you know everything about polynomials!

Regards,

Dave
  #10  
Old 11-May-2007, 05:39
jim mcnamara jim mcnamara is offline
Junior Member
 
Join Date: May 2007
Location: NM
Posts: 38
jim mcnamara will become famous soon enough

Re: combining localtime() members into a single long long


Howard's original question -

mktime returns a time_t (implementation dependent) datatype. On HPUX 11.0it is a 32 bit unsigned long, for example. All of our Linux boxes have it defined as 64 bit.

It seems to me that would work for sorting. Plus, localtime starts out using that same time_t value, so you could skip the intermediate steps. Or did you need to have it in human readable form?
 
 

Recent GIDBlogHalfway done! by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

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

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Strange C++ code memory leakage problem gaoanyu C++ Forum 7 04-Nov-2005 08:09
Quick, Insertion, and Partition silicon C++ Forum 0 18-May-2005 20:49
Merge and Heap...which is really faster silicon C++ Forum 0 10-May-2005 13:46
Insertion Sort Problem silicon C++ Forum 2 08-May-2005 16:13
Sorting Algorithms by Time silicon C++ Forum 4 02-May-2005 21:54

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 17:12.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.