1

I would like to encode data about telephone call on a set of 64 bits.

There is 64 total: int caller(first 17 bits), int caller_zone(next 7 bits), int callee(17 bits), int callee_zone(7 bits), int duration(13 bits), int tariff(3 bits)

After endoding I would like decode it back. I have created encode(...) method which encodes data, but I think it is wrong(because after decoding caller back the number is different).

Question: How to correct encode method and how to decode the data back?

Code compiles and runs(it will be easily understood if ran):

#include "stdafx.h"
#include <iostream>

using namespace std;

unsigned long long encode(int caller, int caller_zone, int callee, int callee_zone, int duration, int tariff){
    //I will shift every number to the left an ammount of times so they will cover seperate area of 64 bits of unsigned long long
    unsigned long long p1 = caller;
    int shift = 64 - 17;//first 17 bits
    p1 = __ll_lshift(p1, shift);
    unsigned long long p2 = caller_zone;
    p2 = __ll_lshift(p2, (shift -= 7));//next 7 bits
    unsigned long long p3 = callee;
    p3 = __ll_lshift(p3, (shift -= 17));//next 17 bits
    unsigned long long p4 = callee_zone;
    p4 = __ll_lshift(p4, (shift -= 7));//next 7 bits
    unsigned long long p5 = duration;
    p5 = __ll_lshift(p5, (shift -= 13));//next 13 bits
    unsigned long long p6 = tariff;//last 3 bits
    return p1 | p2 | p3 | p4 | p5 | p6;
}
void info(long long val){
    unsigned long long val1 = 0;
    //
    int caller; int caller_zone;
    int callee; int callee_zone;
    int duration; int tariff;

    caller = __ll_lshift(ULLONG_MAX & val, 64 - 17);

    cout << "caller:      " << caller << endl;
}
int main(){
    int caller = 130999; int caller_zone = 101;
    int callee = 7777; int callee_zone = 99;
    int duration = 7000; int tariff = 6;
    cout << "FROM MAIN" << endl;
    cout << "caller:      " << caller << endl
        << "caller zone: " << caller_zone << endl
        << "calee:       " << callee << endl
        << "calee zone:  " << callee_zone << endl
        << "duration:    " << duration << endl
        << "tariff:      " << tariff << endl;

    unsigned long long u = encode(caller, caller_zone, callee, callee_zone, duration, tariff);
    cout << u << endl;// do skasowania
    cout << "\n FROM INFO" << endl;
    info(u);
    cout << "cos" << endl;
    int val = 21;
    val = __ll_lshift(val, 1);
    cout << val << endl;
    system("pause");
    return 0;
}
Yoda
  • 17,363
  • 67
  • 204
  • 344
  • Sure about allover endianess of the encoded data? Not that I have a clue about what you're asking for ... – πάντα ῥεῖ May 03 '14 at 23:43
  • @πάνταῥεῖ How can I improe my question? – Yoda May 03 '14 at 23:59
  • _'How can I improe my question?'_ Hard to tell, I **really** don't have a clue! (all that shifting stuff :-/ ...) – πάντα ῥεῖ May 04 '14 at 00:01
  • @πάνταῥεῖ Do you understand what is question about? That I have few numbers and I want to merge them in one 64 bit number. – Yoda May 04 '14 at 00:05
  • 64 bit number representation is machine architecture dependend, that's why I've thrown in the endianess issue here! (for an encoding/decoding context). I've just assumed you might want to sent encoded data over a wire and decode it back. Otherwise simple masking of bits and down(right)-shifting to normalize should get you well off for decoding. – πάντα ῥεῖ May 04 '14 at 00:14
  • Try to print out the bits of each input and the bits of the final output, using one of the tricks here: http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format – merlin2011 May 04 '14 at 00:18
  • Only by looking to see whether the bits match, you can be sure exactly what is right or wrong. – merlin2011 May 04 '14 at 00:18
  • Hey @Yoda, can you share where did you get that question from? – uksz Nov 11 '15 at 17:07
  • @uksz I don't remember, but for sure sb orderded solution, if you name the teacher I might find a student. – Yoda Nov 11 '15 at 23:26

2 Answers2

1

It appears that you are doing the encoding as you intend, although you will have to look at the output of the following program yourself to determine for sure.

I stole a function from this answer, and modified your code a bit to be more portable.

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


using namespace std;


//assumes little endian
void printBits(size_t const size, void const * const ptr)
{
    unsigned char *b = (unsigned char*) ptr;
    unsigned char byte;
    int i, j;

    for (i=size-1;i>=0;i--)
    {
        for (j=7;j>=0;j--)
        {
            byte = b[i] & (1<<j);
            byte >>= j;
            printf("%u", byte);
        }
    }
    puts("");
}

uint64_t encode(int caller, int caller_zone, int callee, int callee_zone, int duration, int tariff){
    uint64_t p1 = caller;
    int shift = 64 - 17;//first 17 bits
    p1 = p1 << shift;
    uint64_t p2 = caller_zone;
    p2 = p2 << (shift -= 7); //next 7 bits
    uint64_t p3 = callee;
    p3 = p3 << (shift -= 17); //next 17 bits
    uint64_t p4 = callee_zone;
    p4 = p4 << (shift -= 7); //next 7 bits
    uint64_t p5 = duration;
    p5 = p5 << (shift -= 13);//next 13 bits
    uint64_t p6 = tariff;//last 3 bits

    printBits(8, &p1);    
    printBits(8, &p2);    
    printBits(8, &p3);    
    printBits(8, &p4);    
    printBits(8, &p5);    
    printBits(8, &p6);    

    uint64_t result = p1 | p2 | p3 | p4 | p5 | p6;
    printBits(8, &result);    
    return result;
}

int main(){
    int caller = 130999; int caller_zone = 101;
    int callee = 7777; int callee_zone = 99;
    int duration = 7000; int tariff = 6;

    unsigned long long u = encode(caller, caller_zone, callee, callee_zone, duration, tariff);
    return 0;
}

Output:

1111111111011011100000000000000000000000000000000000000000000000
0000000000000000011001010000000000000000000000000000000000000000
0000000000000000000000000000111100110000100000000000000000000000
0000000000000000000000000000000000000000011000110000000000000000
0000000000000000000000000000000000000000000000001101101011000000
0000000000000000000000000000000000000000000000000000000000000110
1111111111011011111001010000111100110000111000111101101011000110
Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
1

And here's the decode function:

#include <iostream>
#include <tuple>

using namespace std;

std::tuple<int, int, int, int, int, int> decode(uint64_t bits) {
    int tariff = bits & 0x7;
    bits >>= 3;

    int duration = bits & 0x1fff;
    bits >>= 13;

    int callee_zone = bits & 0x7f;
    bits >>= 7;

    int callee = bits & 0x1ffff;
    bits >>= 17;

    int caller_zone = bits & 0x7f;
    bits >>= 7;

    int caller = bits & 0x1ffff;

    return std::make_tuple(caller, caller_zone, callee, callee_zone, duration, tariff);
}

int main()
{
    uint64_t encodedBits = 0b1111111111011011111001010000111100110000111000111101101011000110;

    int caller = 0; int caller_zone = 0;
    int callee = 0; int callee_zone = 0;
    int duration = 0; int tariff = 0;

    std::tie(caller, caller_zone, callee, callee_zone, duration, tariff) = decode(encodedBits);

    cout << caller << endl
    << caller_zone << endl
    << callee << endl
    << callee_zone << endl
    << duration << endl
    << tariff << endl;

return 0;
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142