How to store three small numbers into one double? - math

I have int A, B, C. And A is in range 0-9999, B is 0-99, C is 0-99.
Because the function must return only one double, I think of putting them all into one number. Otherwise I need to call function three times.
But I cannot write an efficient code to do this. This will be called millions times, so it should be quite effective, but no ASM.
I need a function double pack3int_to_double(int A, int B, int C) {}

Couldn't you just store A + 1000B + 100000C?
For example, if you wanted to store A = 1234, B = 6, and C = 89, you'd just store
89061234
CCBAAAA
You can then extract the numbers by casting the double to an int and using standard integer division and modulus tricks to recover the individual values.
Hope this helps!

If A<10,000 and B & C <100, A can be expressed with 14 bits, and B & C with 8 bits. Thus you need 30 bits in total.
You could therefore pack/unpack the integers by shifting it to the right place:
int packed = A + B<<14 + C<<22;
A = packed & 0x3FFF; B = (packed >> 14) & 0xFF; C = (packed >> 22) & 0xFF;
Bit shifting is of course MUCH faster than multiply/divide, and you can cast the int to a double and vice versa.

This is technically not legal C code, so you would use this at your own risk:
typedef union {
double x;
struct {
unsigned a : 14;
unsigned b : 7;
unsigned c : 7;
} y;
} result_t;
The C standard doesn't allow using a union member to write a value and a different one to read it out, but I am not aware of a compiler that does the static analysis to diagnose such a problem (it doesn't mean one won't do so in the future). Also, using certain int values may result in a trap representation for a double. But, if you know your system will not generate any trap representations, you can consider using this.
double pack3int_to_double(int A, int B, int C) {
result_t r;
r.y.a = A;
r.y.b = B;
r.y.c = C;
return r.x;
}
void unpack3int_from_double (double X, int *A, int *B, int *C) {
result_t r = { X };
*A = r.y.a;
*B = r.y.b;
*C = r.y.c;
}

You can use out parameters in function call and retrieve all 3 int variables.

You could return a NaN double with the data stored in the mantissa. That gives you 53 bits to utilize. Should be plenty.
http://en.m.wikipedia.org/wiki/NaN

Inspired by your answers, this is what I come up so far. This should be quite efficient, and only 32 bits are used, so the exponent of the double is not touched.
struct pack_abc {
unsigned short a;
unsigned char b, c;
int safety;
};
double pack3int_to_double(int A, int B, int C) {
struct pack_abc R = {A, B, C, 0}; // or 0 could be replaced with something smater, like NaN?
return *(double*)&R;
}
void main() {
int w = 1234, a = 56, d = 78;
int W, A, D, i;
double p = pack3int_to_double(w, a, d);
// we got the data packed into 'p', now let's unpack it
struct pack_abc *R = (struct pack_abc*) & p;
printf("%i %i %i\n", (int)R->a, (int)R->b, (int)R->c);
}

Related

Like Bezout's identity but with Natural numbers and an arbitrary constant. Can it be solved?

I'm an amateur playing with discrete math. This isn't a
homework problem though I am doing it at home.
I want to solve ax + by = c for natural numbers, with a, b and c
given and x and y to be computed. I want to find all x, y pairs
that will satisfy the equation.
This has a similar structure to Bezout's identity for integers
where there are multiple (infinite?) solution pairs. I thought
the similarity might mean that the extended Euclidian algorithm
could help here. Below are two implementations of the EEA that
seem to work; they're both adapted from code found on the net.
Could these be adapted to the task, or perhaps can someone
find a more promising avenue?
typedef long int Int;
#ifdef RECURSIVE_EEA
Int // returns the GCD of a and b and finds x and y
// such that ax + by == GCD(a,b), recursively
eea(Int a, Int b, Int &x, Int &y) {
if (0==a) {
x = 0;
y = 1;
return b;
}
Int x1; x1=0;
Int y1; y1=0;
Int gcd = eea(b%a, a, x1, y1);
x = y1 - b/a*x1;
y = x1;
return gcd;
}
#endif
#ifdef ITERATIVE_EEA
Int // returns the GCD of a and b and finds x and y
// such that ax + by == GCD(a,b), iteratively
eea(Int a, Int b, Int &x, Int &y) {
x = 0;
y = 1;
Int u; u=1;
Int v; v=0; // does this need initialising?
Int q; // quotient
Int r; // remainder
Int m;
Int n;
while (0!=a) {
q = b/a; // quotient
r = b%a; // remainder
m = x - u*q; // ?? what are the invariants?
n = y - v*q; // ?? When does this overflow?
b = a; // A candidate for the gcd - a's last nonzero value.
a = r; // a becomes the remainder - it shrinks each time.
// When a hits zero, the u and v that are written out
// are final values and the gcd is a's previous value.
x = u; // Here we have u and v shuffling values out
y = v; // via x and y. If a has gone to zero, they're final.
u = m; // ... and getting new values
v = n; // from m and n
}
return b;
}
#endif
If we slightly change the equation form:
ax + by = c
by = c - ax
y = (c - ax)/b
Then we can loop x through all numbers in its range (a*x <= c) and compute if viable natural y exists. So no there is not infinite number of solutions the limit is min(c/a,c/b) ... Here small C++ example of naive solution:
int a=123,b=321,c=987654321;
int x,y,ax;
for (x=1,ax=a;ax<=c;x++,ax+=a)
{
y = (c-ax)/b;
if (ax+(b*y)==c) here output x,y solution somewhere;
}
If you want to speed this up then just iterate y too and just check if c-ax is divisible by b Something like this:
int a=123,b=321,c=987654321;
int x,y,ax,cax,by;
for (x=1,ax=a,y=(c/b),by=b*y;ax<=c;x++,ax+=a)
{
cax=c-ax;
while (by>cax){ by-=b; y--; if (!y) break; }
if (by==cax) here output x,y solution somewhere;
}
As you can see now both x,y are iterated in opposite directions in the same loop and no division or multiplication is present inside loop anymore so its much faster here first few results:
method1 method2
[ 78.707 ms] | [ 21.277 ms] // time needed for computation
75044 | 75044 // found solutions
-------------------------------
75,3076776 | 75,3076776 // first few solutions in x,y order
182,3076735 | 182,3076735
289,3076694 | 289,3076694
396,3076653 | 396,3076653
503,3076612 | 503,3076612
610,3076571 | 610,3076571
717,3076530 | 717,3076530
824,3076489 | 824,3076489
931,3076448 | 931,3076448
1038,3076407 | 1038,3076407
1145,3076366 | 1145,3076366
I expect that for really huge c and small a,b numbers this
while (by>cax){ by-=b; y--; if (!y) break; }
might be slower than actual division using GCD ...

How do I swap two pointer values without using third variable

*a=10
*b=20
How to swap them without using the third variable? Output should be like
*a=20
*b=10
Not sure if the interviewer was looking for XOR over something else but it seems you can simply use +, -, and x. Should work if a is bigger or negative as well.
*a+=*b
*b-=*a
*b=*b x -1
*a-=*b
In your example that would give us:
*a+=*b --> *a = 30
*b-=*a --> *b = -10
*b=*b x -1 --> *b = 10
*a-=*b --> *a = 20
Here is a simple code to do so:
#include <stdio.h>
#include <stdlib.h>
void usingXOR(int** x, int** y){
unsigned long long a = (unsigned long long)*x;
unsigned long long b = (unsigned long long)*y;
a = a^b;
b = a^b;
a = a^b;
*x = (int*)a;
*y = (int*)b;
}
void main(){
int x=5;
int y=10;
int* a = &x;
int* b = &y;
//If you only want to swap the values the pointers are pointing to
//Here the addresses the pointers are holding dont get swapped
(*a) = (*a)+(*b);
(*b) = (*a)-(*b);
(*a) = (*a)-(*b);
//If you want to swap addresses in the pointers
//printf("Before swap address a: %p\n", a);
//printf("Before swap address b: %p\n", b);
//usingXOR(&a,&b);
printf("a: %d\n", *a);
printf("b: %d\n", *b);
//printf("After swap address a: %p\n", a);
//printf("After swap address b: %p\n", b);
}

Negative Number, Positive Numbers, pointers, and characters

I'm trying to figure out this program; it is an averaging program and it requires user input of:
p 4 p 7 p 2 n 1 e sum 12 average: 4
The user enters whether he was a positive number or negative.
We are asked to use int real_number(int* value) and make value a pointer to where the input value will be stored.
So far I have:
#include <stdio.h>
int real_number(int* value);
int real_number(int* value)
{
char *n = "negative";
char *p = "positive";
char *e = "end";
int *sum = 0;
int *avg = 0;
while(sum = 0)
{
printf(" \n");
scanf("%d", &sum);
}
}
int main()
{
}
I know it is not much, but I'm lost; any ideas?
Firstly you have to read characters while your character is different "e". Secondly you have an infinite cicle. In while loop modify the condition with == .
You need to have a counter to count how many numbers you entered. While you read numbers you must add these numbers to sum and count one.
Finally, in the output you write sum/counter

pointer to arrays of struct

struct a{
double array[2][3];
};
struct b{
double array[3][4];
};
void main(){
a x = {{1,2,3,4,5,6}};
b y = {{1,2,3,4,5,6,7,8,9,10,11,12}};
}
I have two structs, inside which there are two dim arrays with different sizes. If I want to define only one function, which can deal with both x and y (one for each time), i.e., the function allows both x.array and y.array to be its argument. How can I define the input argument? I think I should use a pointer.... But **x.array seems not to work.
For example, I want to write a function PrintArray which can print the input array.
void PrintArray( ){}
What should I input into the parenthesis? double ** seems not work for me... (we can let dimension to be the PrintArray's argument as well, telling them its 2*3 array)
Write a function that takes three parameters: a pointer, the number of rows, and the number of columns. When you call the function, reduce the array to a pointer.
void PrintArray(const double *a, int rows, int cols) {
int r, c;
for (r = 0; r < rows; ++r) {
for (c = 0; c < cols; ++c) {
printf("%3.1f ", a[r * cols + c]);
}
printf("\n");
}
}
int main(){
struct a x = {{{1,2,3},{4,5,6}}};
struct b y = {{{1,2,3,4},{5,6,7,8},{9,10,11,12}}};
PrintArray(&x.array[0][0], 2, 3);
PrintArray(&y.array[0][0], 3, 4);
return 0;
}

Arduino converting between uint32_t and unsigned chars

I'm using the rainbowduino and it has some methods that take individual r g b values as unsigned chars, and some that take a 24bit rgb colour code.
I want to convert r g b values into this 24bit colour code of type uint32_t (so that all my code only has to use r g b values.
Any ideas?
I have already tried uint32_t result = r << 16 + g << 8 + b;
r = 100 g =200 b=0 gave green, but r=0 g=200 b=0 gave nothing
Rb.setPixelXY(unsigned char x, unsigned char y, unsigned char colorR, unsigned char colorG, unsigned char colorB)
This sets the pixel(x,y)by specifying each channel(color) with 8bit number.
Rb.setPixelXY(unsigned char x, unsigned char y, unit32_t colorRGB)
This sets the pixel(x,y)by specifying a 24bit RGB color code.
The drivers code is:
void Rainbowduino::setPixelXY(unsigned char x, unsigned char y, uint32_t colorRGB /*24-bit RGB Color*/)
{
if(x > 7 || y > 7)
{
// Do nothing.
// This check is used to avoid writing to out-of-bound pixels by graphics function.
// But this might slow down setting pixels (remove this check if fast disply is desired)
}
else
{
colorRGB = (colorRGB & 0x00FFFFFF);
frameBuffer[0][x][y]=(colorRGB & 0x0000FF); //channel Blue
colorRGB = (colorRGB >> 8);
frameBuffer[1][x][y]=(colorRGB & 0x0000FF); //channel Green
colorRGB = (colorRGB >> 8);
frameBuffer[2][x][y]=(colorRGB & 0x0000FF); //channel Red
}
}
So I would think similar to the above :
uint8_t x,y,r,b,g;
uint32_t result = (r << 16) | (g << 8) | b;
Rb.setPixelXY(x, y, result);
should work. It I think the above likely needs the parenthesis, to ensure proper ordering, as "+" is higher than "<<". Also likely won't hurt but the "|" is better, as not to prevent undesired carry's.
P.S. Remember when shifting to be unsigned, unless you want arithmetic shift versus logical.
and on that note I don't like shifts as they are often messed up and inefficient. Rather a union is simple and efficient.
union rgb {
uint32_t word;
uint8_t byte[3];
struct {
uint8_t blue;
uint8_t green;
uint8_t red;
} color ;
}rgb ;
// one way to assign by discrete names.
rbg.color.blue = b;
rbg.color.green = g;
rbg.color.red = r;
//or assign using array
rgb.byte[0] = b;
rgb.byte[1] = g;
rgb.byte[2] = r;
// then interchangeably use the whole integer word when desired.
Rb.setPixelXY(x, y, rgb.word);
no messing with keeping track of shifts.
One way to approach this would be to shift the bits to the left...
uint32_t result = r << 16 + g << 8 + b;

Resources