I am writing a function
int are_non_negatives(int* start, int n) {
...
}
This function returns 1 if all the next n integers in the array start are non-negative. It returns 0 otherwise.
My question is if there exist tricks that do this as fast as possible (other than looping and checking every single position)?
Dirty/non-portable tricks are fine. I want to know about those as well. Thanks!
One slightly "dirty/non-portable" trick you could leverage for the worst case where all elements need to be checked: In 2's complement int representation, the highest bit is set if and only if the value is negative. So, you could bitwise OR them all and check the highest bit. This could be done using vector instructions to do batches of them at a time, e.g. 8 elements at a time supposing 32-bit int and 256-bit AVX instructions.
Trying to improve performance is a recurring subject for C programmers. Benchmarking alternatives is necessary to test if optimization is useful and worth the effort. This is a naive implementation for reference:
int are_non_negatives_naive(const int *start, int n) {
while (n --> 0) {
if (*start++ >= 0)
return 0;
}
return 1;
}
On current architectures (two's complement) you can combine blocks of entries and test the sign bit much less often. If the arrays are small, you can combine all elements and use a single test:
int are_non_negatives_full(const int *start, int n) {
int combined = 0;
while (n --> 0) {
combined |= *start++;
}
return combined >= 0;
}
If the arrays sizes are varied, you can combine all elements in chunks and test every chunk, allowing for early bail out if a negative value is present:
int are_non_negatives_chunks(const int *start, int n) {
int combined;
for (; n >= 8; n -= 8, start += 8) {
combined = (start[0] | start[1] | start[2] | start[3] |
start[4] | start[5] | start[6] | start[7]);
if (combined < 0)
return 0;
}
combined = 0;
while (n --> 0) {
combined |= *start++;
}
return combined >= 0;
}
Further performance improvements can be achieved by vectorizing the above, either using portable constructions such using 64-bit types or more specific hardware specific intrinsics. The effort might not be necessary is the compiler can vectorize the above algorithms on its own: clang uses SIMD instructions as can be seen with Godbolt Compiler Explorer.
You could check k elements at a time by casting to the largest integer available and crafting the right mask, eg: if you have an array of char, or int8_t, you could check 8 elements at a time.
The mask is crafted to be all zeroes, except for the sign bits.
This way if one of those chars is negative the bitwise AND of the mask and the cast iterator will be > 0
int8_t _i8[8] = { INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN };
uint64_t mask = *(uint64_t *)_i8;
uint64_t *it = (uint64_t *)a;
size_t i = 0;
if (it[i] & mask)
return FALSE;
Of course you should take care of the remainders of n % k, which can be done with a simple switch like this:
size_t i = 0;
switch (n % 8) {
case 0: if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
}
Here I've made a proof of concept that compares the naive approach, the unrolled approach using the Duff's device, and an unrolled and masked approach that uses both the Duff's device and the masking.
It would require a bit more testing, but seems promising nonetheless.
You can run it here https://onlinegdb.com/SyliIUrSZO
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#define CLOCKS_PER_MSEC (CLOCKS_PER_SEC/1000)
#define TRUE (0 == 0)
#define FALSE (!TRUE)
// 8 bit integers
int are_non_negatives_naive_i8(int8_t *a, size_t n)
{
size_t i;
for (i = 0; i < n; ++i)
if (a[i] < 0)
return FALSE;
return TRUE;
}
int are_non_negatives_unrolled_i8(int8_t *a, size_t n)
{
size_t M = (n + 7) / 8;
size_t i = 0;
switch (n % 8) {
case 0: do { if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
} while (--M > 0);
}
}
int are_non_negatives_unrolled_masked_i8(int8_t *a, size_t n)
{
int8_t _i8[8] = { INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN, INT8_MIN };
uint64_t mask = *(uint64_t *)_i8;
uint64_t *it = (uint64_t *)a;
size_t i = 0;
switch (n % 8) {
case 0: if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
}
size_t N = n / 8;
// for (i = 0; i < N; ++i)
// if (it[i] & mask)
// return FALSE;
size_t M = (N + 7) / 8;
switch (N % 8) {
case 0: do { if (it[i++] & mask) return FALSE;
case 7: if (it[i++] & mask) return FALSE;
case 6: if (it[i++] & mask) return FALSE;
case 5: if (it[i++] & mask) return FALSE;
case 4: if (it[i++] & mask) return FALSE;
case 3: if (it[i++] & mask) return FALSE;
case 2: if (it[i++] & mask) return FALSE;
case 1: if (it[i++] & mask) return FALSE;
} while (--M > 0);
}
return TRUE;
}
//----------------------------------------------------------------
// 16 bit integers
int are_non_negatives_naive_i16(int16_t *a, size_t n)
{
size_t i;
for (i = 0; i < n; ++i)
if (a[i] < 0)
return FALSE;
return TRUE;
}
int are_non_negatives_unrolled_i16(int16_t *a, size_t n)
{
size_t M = (n + 7) / 8;
size_t i = 0;
switch (n % 8) {
case 0: do { if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
} while (--M > 0);
}
}
int are_non_negatives_unrolled_masked_i16(int16_t *a, size_t n)
{
int16_t _i16[4] = { INT16_MIN, INT16_MIN, INT16_MIN, INT16_MIN };
uint64_t mask = *(uint64_t *)_i16;
uint64_t *it = (uint64_t *)a;
size_t i = 0;
switch (n % 8) {
case 0: if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
}
size_t N = n / 4;
// for (i = 0; i < N; ++i)
// if (it[i] & mask)
// return FALSE;
size_t M = (N + 7) / 8;
switch (N % 8) {
case 0: do { if (it[i++] & mask) return FALSE;
case 7: if (it[i++] & mask) return FALSE;
case 6: if (it[i++] & mask) return FALSE;
case 5: if (it[i++] & mask) return FALSE;
case 4: if (it[i++] & mask) return FALSE;
case 3: if (it[i++] & mask) return FALSE;
case 2: if (it[i++] & mask) return FALSE;
case 1: if (it[i++] & mask) return FALSE;
} while (--M > 0);
}
return TRUE;
}
//----------------------------------------------------------------
// 32 bit integers
int are_non_negatives_naive_i32(int32_t *a, size_t n)
{
size_t i;
for (i = 0; i < n; ++i)
if (a[i] < 0)
return FALSE;
return TRUE;
}
int are_non_negatives_unrolled_i32(int32_t *a, size_t n)
{
size_t M = (n + 7) / 8;
size_t i = 0;
switch (n % 8) {
case 0: do { if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
} while (--M > 0);
}
}
int are_non_negatives_unrolled_masked_i32(int32_t *a, size_t n)
{
int32_t _i32[2] = { INT32_MIN, INT32_MIN };
uint64_t mask = *(uint64_t *)_i32;
uint64_t *it = (uint64_t *)a;
size_t i = 0;
switch (n % 8) {
case 0: if (a[i++] < 0) return FALSE;
case 7: if (a[i++] < 0) return FALSE;
case 6: if (a[i++] < 0) return FALSE;
case 5: if (a[i++] < 0) return FALSE;
case 4: if (a[i++] < 0) return FALSE;
case 3: if (a[i++] < 0) return FALSE;
case 2: if (a[i++] < 0) return FALSE;
case 1: if (a[i++] < 0) return FALSE;
}
size_t N = n / 2;
// for (i = 0; i < N; ++i)
// if (it[i] & mask)
// return FALSE;
size_t M = (N + 7) / 8;
switch (N % 8) {
case 0: do { if (it[i++] & mask) return FALSE;
case 7: if (it[i++] & mask) return FALSE;
case 6: if (it[i++] & mask) return FALSE;
case 5: if (it[i++] & mask) return FALSE;
case 4: if (it[i++] & mask) return FALSE;
case 3: if (it[i++] & mask) return FALSE;
case 2: if (it[i++] & mask) return FALSE;
case 1: if (it[i++] & mask) return FALSE;
} while (--M > 0);
}
return TRUE;
}
//----------------------------------------------------------------
void fill_array(void *array, size_t type, size_t n, int contains_negatives)
{
size_t i;
switch (type) {
case 1: {
int8_t *a = array;
for (i = 0; i < n; ++i)
a[i] = rand() % INT8_MAX;
break;
}
case 2: {
int16_t *a = array;
for (i = 0; i < n; ++i)
a[i] = rand() % INT16_MAX;
break;
}
case 4: {
int32_t *a = array;
for (i = 0; i < n; ++i)
a[i] = rand() % INT32_MAX;
break;
}
case 8: {
int64_t *a = array;
for (i = 0; i < n; ++i)
a[i] = rand();
break;
}
}
if (contains_negatives) {
int how_many = rand() % n;
for (int i; i < how_many; ++i) {
int j = rand() % n;
switch (type) {
case 1: {
int8_t *a = array;
a[j] *= -1;
break;
}
case 2: {
int16_t *a = array;
a[j] *= -1;
break;
}
case 4: {
int32_t *a = array;
a[j] *= -1;
break;
}
case 8: {
int64_t *a = array;
a[j] *= -1;
break;
}
}
}
}
}
int main()
{
time_t t;
clock_t clock_start;
clock_t clock_end;
clock_t clock_naive = 0;
clock_t clock_unrolled = 0;
clock_t clock_unrolled_masked = 0;
/* Intializes random number generator */
srand((unsigned long) time(&t));
printf("8 bit integers\n");
printf("----------------------------------------------------------------\n");
int8_t *array_i8;
for (int i = 3; i < 7; ++i) {
size_t size = pow(10, i);
array_i8 = malloc(size * sizeof(int8_t));
printf("------------------------------------------------\n");
printf("%lu elements\n", size);
for (int has_neg = 0; has_neg < 2; ++has_neg) {
printf("--------------------------------\n");
printf("Has negatives: %s\n", has_neg ? "yes": "no");
fill_array(array_i8, sizeof(int8_t), size, has_neg);
int neg_naive;
int neg_unrolled;
int neg_unrolled_masked;
clock_start = clock();
neg_naive = are_non_negatives_naive_i8(array_i8, size);
clock_end = clock();
clock_naive = clock_end - clock_start;
clock_start = clock();
neg_unrolled = are_non_negatives_unrolled_i8(array_i8, size);
clock_end = clock();
clock_unrolled = clock_end - clock_start;
clock_start = clock();
neg_unrolled_masked = are_non_negatives_unrolled_masked_i8(array_i8, size);
clock_end = clock();
clock_unrolled_masked = clock_end - clock_start;
if (!has_neg) {
if (!neg_naive)
printf("Error: neg_naive\n");
if (!neg_unrolled)
printf("Error: neg_unrolled\n");
if (!neg_unrolled_masked)
printf("Error: neg_unrolled_masked\n");
}
printf(" clock_naive: %lu\n", clock_naive);
printf(" clock_unrolled: %lu\n", clock_unrolled);
printf("clock_unrolled_masked: %lu\n", clock_unrolled_masked);
printf("--------------------------------\n");
}
printf("------------------------------------------------\n");
free (array_i8);
array_i8 = NULL;
}
printf("----------------------------------------------------------------\n");
printf("16 bit integers\n");
printf("----------------------------------------------------------------\n");
int16_t *array_i16;
for (int i = 3; i < 7; ++i) {
size_t size = pow(10, i);
array_i16 = malloc(size * sizeof(int16_t));
printf("------------------------------------------------\n");
printf("%lu elements\n", size);
for (int has_neg = 0; has_neg < 2; ++has_neg) {
printf("--------------------------------\n");
printf("Has negatives: %s\n", has_neg ? "yes": "no");
fill_array(array_i16, sizeof(int16_t), size, has_neg);
int neg_naive;
int neg_unrolled;
int neg_unrolled_masked;
clock_start = clock();
neg_naive = are_non_negatives_naive_i16(array_i16, size);
clock_end = clock();
clock_naive = clock_end - clock_start;
clock_start = clock();
neg_unrolled = are_non_negatives_unrolled_i16(array_i16, size);
clock_end = clock();
clock_unrolled = clock_end - clock_start;
clock_start = clock();
neg_unrolled_masked = are_non_negatives_unrolled_masked_i16(array_i16, size);
clock_end = clock();
clock_unrolled_masked = clock_end - clock_start;
if (!has_neg) {
if (!neg_naive)
printf("Error: neg_naive\n");
if (!neg_unrolled)
printf("Error: neg_unrolled\n");
if (!neg_unrolled_masked)
printf("Error: neg_unrolled_masked\n");
}
printf(" clock_naive: %lu\n", clock_naive);
printf(" clock_unrolled: %lu\n", clock_unrolled);
printf("clock_unrolled_masked: %lu\n", clock_unrolled_masked);
printf("--------------------------------\n");
}
printf("------------------------------------------------\n");
free (array_i16);
array_i16 = NULL;
}
printf("----------------------------------------------------------------\n");
printf("32 bit integers\n");
printf("----------------------------------------------------------------\n");
int32_t *array_i32;
for (int i = 3; i < 7; ++i) {
size_t size = pow(10, i);
array_i32 = malloc(size * sizeof(int32_t));
printf("------------------------------------------------\n");
printf("%lu elements\n", size);
for (int has_neg = 0; has_neg < 2; ++has_neg) {
printf("--------------------------------\n");
printf("Has negatives: %s\n", has_neg ? "yes": "no");
fill_array(array_i32, sizeof(int32_t), size, has_neg);
int neg_naive;
int neg_unrolled;
int neg_unrolled_masked;
clock_start = clock();
neg_naive = are_non_negatives_naive_i32(array_i32, size);
clock_end = clock();
clock_naive = clock_end - clock_start;
clock_start = clock();
neg_unrolled = are_non_negatives_unrolled_i32(array_i32, size);
clock_end = clock();
clock_unrolled = clock_end - clock_start;
clock_start = clock();
neg_unrolled_masked = are_non_negatives_unrolled_masked_i32(array_i32, size);
clock_end = clock();
clock_unrolled_masked = clock_end - clock_start;
if (!has_neg) {
if (!neg_naive)
printf("Error: neg_naive\n");
if (!neg_unrolled)
printf("Error: neg_unrolled\n");
if (!neg_unrolled_masked)
printf("Error: neg_unrolled_masked\n");
}
printf(" clock_naive: %lu\n", clock_naive);
printf(" clock_unrolled: %lu\n", clock_unrolled);
printf("clock_unrolled_masked: %lu\n", clock_unrolled_masked);
printf("--------------------------------\n");
}
printf("------------------------------------------------\n");
free (array_i32);
array_i32 = NULL;
}
printf("----------------------------------------------------------------\n");
}
Any suggestions or fixes are more than welcome
Note that this solution is not standard and depends on the alignment of the data types.
Albeit it'll usually work, you should check it with something like this
#include <stdio.h>
#include <stdint.h>
#include <stdalign.h>
int main()
{
printf(
"alignof(int8_t ): %lu\n"
"alignof(int16_t): %lu\n"
"alignof(int32_t): %lu\n"
"alignof(int64_t): %lu\n",
alignof(int8_t),
alignof(int16_t),
alignof(int32_t),
alignof(int64_t)
);
return 0;
}
I suspect that this won’t work for you based on the context of your question, but in case your code allows for you to capture array operations (initialization, insertion, modification, deletion), you can coherently maintain a separate list of all elements with negative values. If you have the freedom to do that, it would just be a space-speed tradeoff.
Related
I have this problem with my 8051 project. I want to enter numbers and operation with keypad and print them in 16x2 LCD and the result using 8051 microcontroller. Everything works fine, I can do basic operations and see the results. But when I'm pressing characters from keypad, LCD prints the character twice. I couldn't see where the problem is. I'd be very glad if you help me. Thank you.
#include <reg51.h>
void lcdcmd(unsigned char);
void lcddata(unsigned char);
void MSDelay(unsigned int);
void disp_num(float num);
int get_num(char ch);
void lcdinit();
char scan_key(void);
sfr ldata = 0xA0;
sbit rs = P3^7;
sbit rw = P3^5;
sbit en = P3^6;
sbit r0=P1^0;
sbit r1=P1^1;
sbit r2=P1^2;
sbit r3=P1^3;
sbit c0=P1^4;
sbit c1=P1^5;
sbit c2=P1^6;
sbit c3=P1^7;
void lcdinit(){
MSDelay(15000);
lcdcmd(0x30);
MSDelay(4500);
lcdcmd(0x30);
MSDelay(300);
lcdcmd(0x30);
MSDelay(600);
lcdcmd(0x38);
lcdcmd(0x0F);
lcdcmd(0x01);
lcdcmd(0x06);
lcdcmd(0x80);
}
int main (void)
{
while(1){
unsigned int k=0, m=0, n=0;
int k2, k1;
char key, key1;
unsigned char ch2,ch3;
lcdinit();
key = scan_key();
k2 = get_num(key); // sayiya cevirdik.
lcddata(key); // lcd de goruntule.
ch2 = scan_key();
lcddata(ch2);
key1 = scan_key();
k1 = get_num(key1);
lcddata(key1);
ch3 = scan_key();
lcddata(ch3);
lcdcmd(0x01);
switch(ch2)
{
case 'A':
disp_num(k1 + k2);
break;
case 'B':
disp_num(k2 - k1);
break;
case 'C':
disp_num(k2 * k1);
break;
case 'D':
disp_num(k2 / k1);
break;
}
return 0;
}
}
void lcdcmd(unsigned char value)
{
ldata = value;
rs = 0;
rw = 0;
en = 1;
MSDelay(50);
en = 0;
MSDelay(50);
}
void lcddata(unsigned char value)
{
ldata = value;
rs = 1;
rw = 0;
en = 1;
MSDelay(50);
en = 0;
MSDelay(50);
}
void MSDelay(unsigned int itime)
{
unsigned int i, j;
for(i = 0;i < itime; i++)
for(j = 0; j < 5; j++);
}
char scan_key()
{
unsigned char c;
c='s';
while(!(c=='0' && c=='1' && c=='2' && c=='3' && c=='4'
&& c=='5' && c=='6' && c=='7' && c=='8'
&& c=='9' && c=='+' && c=='-' && c=='#'
&& c=='$' && c=='*' && c=='/' ))
{
r0 = 0; r1 = 1; r2 = 1; r3 = 1;
if(c0==0 && r0==0){ lcddata('7'); MSDelay(100000); return c = '7';}
if(c1==0 && r0==0){ lcddata('8'); MSDelay(100000); return c = '8';}
if(c2==0 && r0==0){ lcddata('9'); MSDelay(100000); return c = '9';}
if(c3==0 && r0==0){ lcddata('A'); MSDelay(100000); return c = 'A';}
r0 = 1; r1 = 0; r2 = 1; r3 = 1;
if(c0==0 && r1==0){ lcddata('4'); MSDelay(100000); return c= '4';}
if(c1==0 && r1==0){ lcddata('5'); MSDelay(100000); return c= '5';}
if(c2==0 && r1==0){ lcddata('6'); MSDelay(100000); return c= '6';}
if(c3==0 && r1==0){ lcddata('B'); MSDelay(100000); return c= 'B';}
r0 = 1; r1 = 1; r2 = 0; r3 = 1;
if(c0==0 && r2==0){ lcddata('1');MSDelay(100000); return c= '1';}
if(c1==0 && r2==0){ lcddata('2');MSDelay(100000); return c= '2';}
if(c2==0 && r2==0){ lcddata('3');MSDelay(100000); return c= '3';}
if(c3==0 && r2==0){ lcddata('C');MSDelay(100000); return c= 'C';}
r0 = 1; r1 = 1; r2 = 1; r3 = 0;
if(c0==0 && r3==0){ lcddata('*');MSDelay(100000);return c= '*';}
if(c1==0 && r3==0){ lcddata('0');MSDelay(100000);return c= '0';}
if(c2==0 && r3==0){ lcddata('#');MSDelay(100000);return c= '#';}
if(c3==0 && r3==0){ lcddata('D');MSDelay(100000);return c= 'D';}
}
return 0;
}
int get_num(char ch) //convert char into int
{
switch(ch)
{
case '0': return 0; break;
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
}
return 0;
}
void disp_num(float num) //displays number on LCD
{
unsigned char UnitDigit = 0; //It will contain unit digit of numb
unsigned char TenthDigit = 0; //It will contain 10th position digit of numb
unsigned char decimal = 0;
int j;
int numb;
j=(int)(num*10);
numb=(int)num;
TenthDigit = (numb/10); // Findout Tenth Digit
if( TenthDigit != 0) // If it is zero, then don't display
lcddata(TenthDigit+0x30); // Make Char of TenthDigit and then display it on LCD
UnitDigit = numb - TenthDigit*10;
lcddata(UnitDigit+0x30); // Make Char of UnitDigit and then display it on LCD
MSDelay(2000000);
}
I solved the probem by removing lcddata() functions from here:
key = scan_key();
k2 = get_num(key); // sayiya cevirdik.
lcddata(key); // lcd de goruntule.
ch2 = scan_key();
lcddata(ch2);
key1 = scan_key();
k1 = get_num(key1);
lcddata(key1);
ch3 = scan_key();
lcddata(ch3);
lcdcmd(0x01);
I didn't understand what you were trying to say about while() in scan_key() function, it works fine in the simulation. But now I want to create a 20 seconds delay for the result in this operation, I tried it with MSDelay() function but nothing changed.
Edit: sorry guys, now I realized the mistake in the while(). That was a huge mistake, I'll fix that and thank you all.
I ran compile this:
char get_credit_card_status(long long credit_card_number, char Luhn_validity)//, char credit_card_status)
{
char credit_card_status = 0;
if (((credit_card_number < 350000000000000) && (340000000000000 <=credit_card_number)) && (Luhn_validity=1))
{
credit_card_status = 1;
printf("1 test\n");
}
else if ((5100000000000000<= credit_card_number) && (credit_card_number < 5500000000000000) && Luhn_validity)
{
credit_card_status = 2;
printf("2 test\n");
}
else if ((((4000000000000<= credit_card_number)&&(credit_card_number<5000000000000)) || ((4000000000000000<=credit_card_number)&&(credit_card_number<5000000000000000))) && Luhn_validity)
{
credit_card_status= 3;
printf("3 test\n");
}
return credit_card_status;
}
int length_ccn(long long credit_card_number)
{
int length = 0;
while (credit_card_number > 0)
{
length++;
credit_card_number /= 10 ;
}
return length;
}
char Luhn_check(long long credit_card_number)
{
int total_even_numbers = 0;
int total_odd_numbers = 0;
int even_number = 0;
int odd_number = 0;
int Luhn_sum = 0;
char Luhn_validity = 0;
long long check_digit_basis = credit_card_number;
for(int i =1 ; check_digit_basis > 0 ; i++)
{
if ((i % 2) > 0)
{
odd_number = (check_digit_basis % 10);
total_odd_numbers = total_odd_numbers + odd_number;
}
else
{
even_number = (check_digit_basis % 10);
if(even_number >= 5)
{
total_even_numbers = total_even_numbers + ((( 2 * even_number) % 10) + 1 );
}
else
{
total_even_numbers = total_even_numbers + (2 * even_number);
}
}
check_digit_basis = (check_digit_basis / 10);
}
Luhn_sum = total_even_numbers + total_odd_numbers;
if ((Luhn_sum % 10 ) == 0 )
{
Luhn_validity = 1;
}
else
{
Luhn_validity = 0;
printf("%c for Luhn_validity\n", Luhn_validity);
}
printf("%d for Luhn_validity\n", Luhn_validity);
return Luhn_validity;
}
int main(void)
{
printf("Provide your credit card number:\n");
long long credit_card_number = get_long_long();
int length = length_ccn(credit_card_number);
printf("%i for length\n", length);
char Luhn_validity = Luhn_check(credit_card_number);
printf("%c returned from line 119\n", Luhn_validity);
char credit_card_status;
credit_card_status = get_credit_card_status(credit_card_number, Luhn_validity);
switch (credit_card_status)
{
case 1:
printf("American Express\n");
break;
case 2:
printf("MasterCard\n");
break;
case 3:
printf("Visa\n");
break;
default:
printf("INVALID\n");
}
}
I got:
15 for length
1 for Luhn_validity
returned from line 119
The value of Length is returned to the main function while Luhn_validity isn't. Why?
I cannot make another post because someone posted an incomplete answer only answering to what I already began to implement (see the post before its edits and you'll see that the boolean problem was being corrected and wasn't in the post's title).
credit_card_status = credit_card_status(credit_card_number)
You try to use the same name, credit_card_status, for two different things. If the function is called credit_card_status don't store it's return value in credit_card_status, because that's the function and not a variable. This leads to the error that credit_card_status is not assignable.
error: comparison of constant 350000000000000 with boolean expression is always true
There is no "twoway" comparison a <= x < b in C, you have to use two separate comparisons: a <= x && x < b.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
What is the difference between these two codes? I think it's same code.
It can't operate both of codeup and Visual Studio.
codeup.kr 1505 problem
The problem for array
when you put number it
it makes num*num array
For example, given num = 3, it creates:
1 2 3
8 9 4
7 6 5
Code 1:
#include<stdio.h>
#include<string.h>
int main()
{
int tile[52][52];
int x, y;
int num;
int start = 1;
int check = 1, complete = 1;
int i;
scanf("%d", &num);
memset(tile, 0, 4 * 52 * 52);
tile[0][1] = 10;
tile[1][num + 1] = 10;
tile[num + 1][num + 1] = 10;
tile[num + 1][0] = 10;
x = 1; y = 1;
for (i = 0; i <= 3000; i++)
{
switch (check)
{
case 1:
{
if (tile[x][y + 1] != 0)
{
check += 1;
break;
}
tile[x][y++] = start;
start++;
complete++;
break;
}
case 2:
{
if (tile[x + 1][y] != 0)
{
check += 1;
break;
}
tile[x++][y] = start;
start++;
complete++;
break;
}
case 3:
{
if (tile[x][y - 1] != 0)
{
check += 1;
break;
}
tile[x][y--] = start;
start++;
complete++;
break;
}
case 4:
{
if (tile[x - 1][y] != 0)
{
check = 1;
break;
}
tile[x--][y] = start;
start++;
complete++;
break;
}
}
if (complete == num*num)
{
break;
}
}
if (num % 2 == 0)
{
tile[x][y] = start;
}
else
{
tile[x][y++] = start;
}
for (x = 1;x <= num; x++)
{
for (y = 1; y <= num; y++)
{
printf("%d ", tile[x][y]);
}
printf("\n");
}
}
This code operates in Visual Studio.
#include<stdio.h>
int main()
{
int tile[52][52];
int x, y;
int num;
int start = 1;
int check = 1, complete = 1;
int i;
scanf("%d", &num);
for (x = 0;x <= num; x++)
{
for (y = 0; y <= num; y++)
{
tile[x][y] = 0;
}
}
tile[0][1] = 10;
tile[1][num+1] = 10;
tile[num + 1][num + 1] = 10;
tile[num + 1][0] = 10;
x = 1; y = 1;
for (i = 0; i <= 3000; i++)
{
switch (check)
{
case 1:
{
if (tile[x][y + 1] != 0)
{
check += 1;
break;
}
tile[x][y++] = start;
start++;
complete++;
break;
}
case 2:
{
if (tile[x + 1][y] != 0)
{
check += 1;
break;
}
tile[x++][y] = start;
start++;
complete++;
break;
}
case 3:
{
if (tile[x][y - 1] != 0)
{
check += 1;
break;
}
tile[x][y--] = start;
start++;
complete++;
break;
}
case 4:
{
if (tile[x - 1][y] != 0)
{
check = 1;
break;
}
tile[x--][y] = start;
start++;
complete++;
break;
}
}
if (complete == num*num)
{
break;
}
}
if (num % 2 == 0)
{
tile[x][y] = start;
}
else
{
tile[x][y++] = start;
}
for (x = 1;x <= num; x++)
{
for (y = 1; y <= num; y++)
{
printf("%d ", tile[x][y]);
}
printf("\n");
}
}
The difference:
$ diff -w one.c two.c2,3d1
< #include<string.h>
<
14,15c12,16
< memset(tile, 0, 4 * 52 * 52);
<
---
> for (x = 0; x <= num; x++) {
> for (y = 0; y <= num; y++) {
> tile[x][y] = 0;
> }
> }
95a97
>
so, the first one uses memset to set all entries of tile to 0 (zero) and the second one uses a loop to set only the entries of tile to zero that are used, the content of the rest of the cells is undefined, could be everything. You can look for some places where x and/or y are outside of 0 <= x <= num < 52 in your code, or step through with a debugger, or use printf()s to find the exact places.
If you do not want to use memset() or are not able too: just change the loop to zero every cell out:
for (x = 0; x < 52; x++) {
for (y = 0; y < 52; y++) {
tile[x][y] = 0;
}
}
I have a problem with function which should print any type of integer on my KS0108 lcd. Here the problem is: when i want to copy void* numb value to void* temp in first swtich - nothing happens. in second switch when use %I get 0. (value of void* numb is about 48 and type _uint8_t)
Code:
void glcd_WriteInt(void* numb, type type)
{
void* temp = 0;
int8_t buff[10];
int8_t size = 0;
int8_t flag = 1;
int8_t sign = 1;
switch(type)
{
case _int8_t: memcpy(temp, numb, sizeof(int8_t)); break;
case _int16_t: memcpy(temp, numb, sizeof(int16_t)); break;
case _int32_t: memcpy(temp, numb, sizeof(int32_t)); break;
case _int64_t: /*memcpy(temp, numb, sizeof(int64_t)); break;*/return; //if want 64 - uncomment
case _uint8_t: *(uint8_t*) temp = *(uint8_t*) numb/*memcpy(temp, numb, sizeof(uint8_t))*/; break;
case _uint16_t: memcpy(temp, numb, sizeof(uint16_t)); break;
case _uint32_t: memcpy(temp, numb, sizeof(uint32_t)); break;
case _uint64_t: /*memcpy(temp, numb, sizeof(uint64_t)); break;*/return; //if want 64 - uncomment
}
while(flag)
{
switch(type)
{
case _int8_t:
buff[size] = *(int8_t*) temp % 100;
flag = (*(int8_t*) temp /= 100) != 0;
break;
case _int16_t:
buff[size] = *(int16_t*) temp % 100;
flag = (*(int16_t*) temp /= 100) != 0;
break;
case _int32_t:
buff[size] = *(int32_t*) temp % 100;
flag = (*(int32_t*) temp /= 100) != 0;
break;
case _int64_t:
/*buff[size] = *(int64_t*) temp % 100; //if want 64 - uncomment
flag = (*(int64_t*) temp /= 100) != 0;*/
break;
case _uint8_t:
buff[size] = *(uint8_t*) temp % 100;
flag = (*(uint8_t*) temp /= 100) != 0;
break;
case _uint16_t:
buff[size] = *(uint16_t*) temp % 100;
flag = (*(uint16_t*) temp /= 100) != 0;
break;
case _uint32_t:
buff[size] = *(uint32_t*) temp % 100;
flag = (*(uint32_t*) temp /= 100) != 0;
break;
case _uint64_t:
/*buff[size] = *(uint64_t*) temp % 100; //if want 64 - uncomment
flag = (*(uint64_t*) temp /= 100) != 0;*/
break;
}
if(buff[size] < 0){
buff[size] = -buff[size];
sign = -1;
}
size++;
}
if(sign == -1) glcd_Character((char) 45);
glcd_WIntTab(buff, size);
}
I tried versions with memcpy, and like here: casts. It is suprising that this function was OK a few days ago.
Your main problem is that you have
void *temp = 0;
declared, and you try to write to a NULL pointer since you initialize it with void *temp = 0.
Even if you don't initialize it, it wont work because it wouldn't be a valid pointer, so either you allocate memory with malloc and assign it to the void *temp pointer, or use a union this way
union Type {
int8_t _int8_t;
int16_t _int16_t;
int32_t _int32_t;
int64_t _int64_t;
uint8_t _uint8_t;
uint16_t _uint16_t;
uint32_t _uint32_t;
uint64_t _uint64_t;
};
void glcd_WriteInt(void* numb, enum type type)
{
union Type temp;
int8_t buff[10];
int8_t size = 0;
int8_t flag = 1;
int8_t sign = 1;
switch (type)
{
case _int8_t: memcpy(&temp, numb, sizeof(int8_t)); break;
case _int16_t: memcpy(&temp, numb, sizeof(int16_t)); break;
case _int32_t: memcpy(&temp, numb, sizeof(int32_t)); break;
case _int64_t: /*memcpy(&temp, numb, sizeof(int64_t)); break;*/return; //if want 64 - uncomment
case _uint8_t: memcpy(&temp, numb, sizeof(uint8_t))/*memcpy(temp, numb, sizeof(uint8_t))*/; break;
case _uint16_t: memcpy(&temp, numb, sizeof(uint16_t)); break;
case _uint32_t: memcpy(&temp, numb, sizeof(uint32_t)); break;
case _uint64_t: /*memcpy(&temp, numb, sizeof(uint64_t)); break;*/return; //if want 64 - uncomment
}
while (flag)
{
switch (type)
{
case _int8_t:
buff[size] = temp._int8_t % 100;
flag = (temp._int8_t /= 100) != 0;
break;
case _int16_t:
buff[size] = temp._int16_t % 100;
flag = (temp._int16_t /= 100) != 0;
break;
case _int32_t:
buff[size] = temp._int32_t % 100;
flag = (temp._int32_t /= 100) != 0;
break;
case _int64_t:
buff[size] = temp._int64_t % 100;
flag = (temp._int64_t /= 100) != 0;
break;
case _uint8_t:
buff[size] = temp._uint8_t % 100;
flag = (temp._uint8_t /= 100) != 0;
break;
case _uint16_t:
buff[size] = temp._uint16_t % 100;
flag = (temp._uint16_t /= 100) != 0;
break;
case _uint32_t:
buff[size] = temp._uint32_t % 100;
flag = (temp._uint32_t /= 100) != 0;
break;
case _uint64_t:
buff[size] = temp._uint64_t % 100;
flag = (temp._uint64_t /= 100) != 0;
break;
}
if (buff[size] < 0)
{
buff[size] = -buff[size];
sign = -1;
}
size++;
}
if (sign == -1)
glcd_Character((char) 45);
glcd_WIntTab(buff, size);
}
I believe the union is a better solution.
I have to output each string in 'ZOJ' order. the length of string is from 1 to 100. The 'E' means the end of the input.
I test my program with gcc. I try so many examples and the output is fine. However, the online judge turn out to be wrong answer.
Example:
Input:
ZZOOOJJJ
ZZZZOOOOOJJJ
ZOOOJJ
E
Output:
ZOJZOJOJ
ZOJZOJZOJZOO
ZOJOJO
Thank you!
Here is my code.
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 100
main() {
char data[MAX_SIZE];
int len;
int z,o,j;
int i;
char c;
int z_index, o_index,j_index;
while(scanf("%s", data)!= EOF && (strlen(data)>=1 && data[0] != 'E')) {
len = strlen(data);
z = -1;
o = -1;
j = -1;
z_index = -1;
o_index = -1;
j_index = -1;
for(i=0; i<len; i++) {
c = data[i];
switch(c) {
case 'Z':
if(z==-1)
z_index=i,z=i;
else
z = i;
break;
case 'O':
if(o==-1)
o_index=i,o=i;
else
o = i;
break;
case 'J':
if(j==-1)
j_index=i,j=i;
else
j = i;
break;
}
}
while(z_index!=-1 || o_index!=-1 || j_index!=-1) {
if(z_index!=-1 && z_index<=z)
putchar('Z'), z_index++;
else
z_index = -1;
if(o_index!=-1 && o_index<=o)
putchar('O'), o_index++;
else
o_index = -1;
if(j_index!=-1 && j_index<=j)
putchar('J'), j_index++;
else
j_index = -1;
}
putchar('\n');
}
}
You should really make your function int main() rather than just main() therefore you should then return 0 at the end.
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 100
int main() {
char data[MAX_SIZE];
int len;
int z,o,j;
int i;
char c;
int z_index, o_index,j_index;
while(scanf("%s", data)!= EOF && (strlen(data)>=1 && data[0] != 'E')) {
len = strlen(data);
z = -1;
o = -1;
j = -1;
z_index = -1;
o_index = -1;
j_index = -1;
for(i=0; i<len; i++) {
c = data[i];
switch(c) {
case 'Z':
if(z==-1)
z_index=i,z=i;
else
z = i;
break;
case 'O':
if(o==-1)
o_index=i,o=i;
else
o = i;
break;
case 'J':
if(j==-1)
j_index=i,j=i;
else
j = i;
break;
}
}
while(z_index!=-1 || o_index!=-1 || j_index!=-1) {
if(z_index!=-1 && z_index<=z)
putchar('Z'), z_index++;
else
z_index = -1;
if(o_index!=-1 && o_index<=o)
putchar('O'), o_index++;
else
o_index = -1;
if(j_index!=-1 && j_index<=j)
putchar('J'), j_index++;
else
j_index = -1;
}
putchar('\n');
}
return 0;
}