1

I wrote a program to solve the exercise below. I got my hours and minutes right, but I cannot get my seconds right.

In order to save disk space Time field in the directory entry is 2 bytes long. Distribution of different bits which account for hours, minutes and seconds is given below:

15 14 13 12 11|10  9  8  7  6  5| 4  3  2  1  0
 H  H  H  H  H| M  M  M  M  M  M| S  S  S  S  S

Write a C++ Program that take input two-byte time entry and appropriately separates hours, minutes and seconds using suitable bitwise operators.

#include<iostream>
using namespace std;
int main()
{
    unsigned int hours, mins, secs;
    unsigned int time;
    cout << "enter time ";
    cin >> time;
    hours = (time >> 11);
    mins = ((time << 5) >> 10); 
    secs = ((time << 11) >> 11);
    cout << hours << "  " << mins << "  " << secs << endl;
    return 0;
}

To get the minutes, I shift the input to the left by 5 positions, hoping to eliminate all the H bits, and then shift to the right by 10 positions to eliminate all the S bits and have the M bits at the rightmost position.

Similarly for the seconds.

However, if I enter 445 I expect the result to be 13 minutes and 29 seconds, but the program outputs 0 13 445.

Why do the hours and minutes appear to come out correctly, but not the seconds?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
lyb
  • 33
  • 6
  • "the following question" – which question? – mkrieger1 Feb 19 '18 at 15:11
  • "cannot get my seconds right" – what do you consider "right"? what do you get instead? – mkrieger1 Feb 19 '18 at 15:12
  • Can you show some examples of how you use this: what you enter as input, what you expect as output, and what you actually get? – mkrieger1 Feb 19 '18 at 15:13
  • 3
    `((time<<11)>>11)&9` yeah, this doesn't seem right. – vgru Feb 19 '18 at 15:13
  • if the user is typing in the time, you probably need to be more careful than bit shifting. it's not clear that the format of time is to me at least. And nothing to make sure they type only digits, hex, decmial, 24 or 12 hour clock, AM/PM,etc.. – kenny Feb 19 '18 at 15:16
  • i edited my question can you please have look and help me out @kenny – lyb Feb 19 '18 at 15:34
  • i get 0 hrs 13 mins 445 secs instead of 29 secs @mkrieger1 – lyb Feb 19 '18 at 15:35
  • "Distribution of different bits which account for hours, minutes and seconds is given below" – where? I don't see it. Please include all necessary details and examples *in the question itself* (not in the comments). – mkrieger1 Feb 19 '18 at 15:39
  • i added a link in the queston @mkrieger1 – lyb Feb 19 '18 at 15:44
  • Why not divide by 60 and eliminate the hassles of debugging bit twiddling code? – Thomas Matthews Feb 19 '18 at 15:46
  • probaby because thats the topic , manipulating bits otherwise it wouldve been easy @ThomasMatthews – lyb Feb 19 '18 at 15:50
  • @mkrieger1 thankyou – lyb Feb 19 '18 at 15:55
  • You need to mask your values so you include only the bits you are interested in for each step. Like this: https://ideone.com/rLiDCR – Retired Ninja Feb 27 '18 at 14:16

4 Answers4

1

You are assuming that the size of unsigned int is 16 bit but it is normally implemented as 32bit integer on nowadays machines.

If you would use uint16_t for the variable time instead it should work.

To use uint16_t include the header stdint.h.

#include <iostream>
#include <stdint.h>

using namespace std;

int main()
{
    uint16_t hours, mins, secs;
    uint16_t time = 445;
    hours = (time >> 11);
    mins = ((time << 5) >> 10);
    secs = (time << 11);
    secs >>= 11;
    cout << hours << "  " << mins << "  " << secs << endl;
    return 0;
}

(Tested on QT 5.5)

chrmue
  • 1,552
  • 2
  • 18
  • 35
  • You should test your answer. It isn't correct. https://ideone.com/Dd0AhH – Retired Ninja Feb 27 '18 at 14:19
  • I tested it on a real machine with QtCreator and there it works. – chrmue Feb 27 '18 at 14:30
  • Your example works for the seconds value, but before when you just suggested the op replace int with uint16_t did not. Do you know why? Try your example with 0xffff and observe the minutes value. – Retired Ninja Feb 27 '18 at 14:41
  • Also consider that `secs = (uint16_t(time << 11) >> 11);` also works. What's the type of that temporary without the cast or assigning it back to a uint16_t? You're on to something that makes this question and answer more interesting than it would seem. – Retired Ninja Feb 27 '18 at 14:54
1
secs = time & 0x1F; // This should give the 5 bits you're expecting for seconds.
Archie Yalakki
  • 512
  • 4
  • 12
  • This shurly is a better solution for the given problem. (But he won't understand why his implementation fails...) – chrmue Feb 27 '18 at 14:37
0

You should zero the bits that don't correspond to the part of time you are looking at. I will use binary literals (which are available in C++14), but comment the equivalent hex literals.

struct time {
    time(unsigned = 0); // also default constructs
    unsigned hours;
    unsigned mins;
    unsigned secs;
}

time::time(unsigned packed) : 
    hours((packed & 0b1111100000000000) >> 11), // 0xF800
    mins ((packed & 0b0000011111100000) >> 5 ), // 0x07E0
    secs ((packed & 0b0000000000011111)      )  // 0x001F
 { }

#include<iostream>

std::ostream& operator<< (std::ostream& os, time t) {
    return os << t.hours << "  " << t.mins << "  " << t.secs;
}

int main()
{
    time t(445);
    std::cout << t << std::endl;
    return 0;
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
0

The task given is impossible, because 6 bits are required for both the minutes and the seconds. You have alotted 5 bits for the seconds.

  • 2^5=32
  • 2^6=64

Using this scheme, 17 bits are required to represent the time.

shizhen
  • 12,251
  • 9
  • 52
  • 88