strange behavior in for loop - a bug? - c++

I'm working with Visual Studio 2012 on a Windows 7 machine and when trying to run the following code snippet (compiled with the default VC11 C++ compiler in x64 mode) the assertion fails, which means, that the inner loop is never entered:
void loopTest1()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-k; n<=m+k; ++n)
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Now I change the inner loop's end condition:
void loopTest2()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
int l = m+k; // this line was added
for (int n=m-k; n<=l; ++n) // m+k was replaced by l
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Then I get the correct result:
acc: 2
acc: 3
acc: 2
When I replace the const unsigned int k by a hard-coded 1, it works, too:
void loopTest3()
{
//const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-1; n<=m+1; ++n) //replaced k with 1
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Does the compiler perform some false optimizations?
Or is there any specific reason, why the behavior in the first case is at least unexpected?

Your int m is going to be promoted to an unsigned int. On the first loop, that means m-k is equal to -1 as an unsigned value, which is the maximum unsigned value and obviously greater than m+k (when n is compared, it gets promoted). To put it in perspective, you'll end up with n being an unsigned representation of -1 and m+k being 1. Of course when you store that -1 unsigned into a signed integer, it overflows and is technically undefined behaviour. It's most likely keeping its -1 representation and then being promoted back to a max unsigned value.
Here's a summary of sorts of the first iteration:
Iteration 1:
m: 0
k: 1u
n=m-k: -1u = max uint, stored into signed int
m+k: 1u
n<=m+k --> max uint <= 1u
In your second example, n is not promoted when compared to the other signed integer and it compares two signed integers. In your third, nothing is unsigned.

Related

Converting an array of decimals to 8-bit binary form in c++

Okay so I'm tryna create a program that:
(1) swaps my array
(2) performs caesar cipher substitution on the swapped array
(3) convert the array from (2) that is in decimal form into 8-bit binary form
And so far I've successfully done the first 2 parts but I'm facing problem with converting the array from decimal to binary form.
And this is my coding of what I've tried
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void swapfrontback(int a[], int n);
int main()
{
int a[10], i, n;
cout << "enter size" << endl;
cin >> n;
if (n == 0)
{
cout << "Array is empty!\n";
}
else
{
cout << "p = " << endl;
for (i = 0; i < n; i++)
{
cin >> a[i];
}
}
swapfrontback(a,n);
//caesar cipher
int shift = 0;
cout << "input shift: ";
cin >> shift;
int modulus = 0;
cout << "input modulus: ";
cin >> modulus;
cout << "p''=" << endl;
for (i = 0; i < n; i++)
{
a[i] = (a[i] + shift) % modulus;
cout << a[i] << endl;
}
// Function that convert Decimal to binary
int b;
b = 8;
cout<< "p'''=" << endl;
for (i = 0; i < n; i++)
{
for(int i=b-1;i>=0;i--)
{
if( a[i] & ( 1 << i ) ) cout<<1;
else cout<<0;
}
}
return 0;
}
void swapfrontback(int a[], int n)
{
int i, temp;
for (i = 0; i < n / 2; i++)
{
temp = a[i];
a[i] = a[n - i-1];
a[n - i-1] = temp;
}
cout << "p' = '" << endl;
for (i = 0; i < n; i++)
{
cout << a[i] << endl;
}
}
the problem is that instead of converting the array of decimal from the 2nd part which is the caesar cipher into its binary form, I'm getting 000000010000000100000001 .
My initial array is
3
18
25
Shift 8 and modulo 26. If anyone knows how to fix this please do help me.
Well, there seems to be something that may be an issue in the future (like the n being larger than 10, but, regarding your question, this nested for sentence is wrong.
for (i = 0; i < n; i++)
{
for(int i=b-1;i>=0;i--) //here you are using the variable 'i' twice
{
if( a[i] & ( 1 << i ) ) cout<<1; //i starts at 7, which binary representation in 4 bits is 0111
else cout<<0;
}
}
When you're using nested for sentences, it is a good idea to not repeat their iterating variables' names since they can affect each other and create nasty things like infinite loops or something like that. Try to use a different variable name instead to avoid confusion and issues:
for(int j=b-1;j>=0;j--) //this is an example
Finally, the idea behind transforming a base 10 number to its binary representation (is to use the & operator with the number 1 to know if a given bit position is a 1 (true) or 0 (false)) for example, imagine that you want to convert 14 to its binary form (00001110), the idea is to start making the & operation with the number 1, an continue with powers of 2 (since them will always be a number with a single 1 and trailing 0s) 1-1 2-10 4-100 8-1000, etc.
So you start with j = 1 and you apply the & operation between it and your number (14 in this case) so: 00000001 & 00001110 is 0 because there is not a given index in which both numbers have a '1' bit in common, so the first bit of 14 is 0, then you either multiply j by two (j*=2), or shift their bits to the left once (j = 1<<j) to move your bit one position to the left, now j = 2 (00000010), and 2 & 14 is 2 because they both have the second bit at '1', so, since the result is not 0, we know that the second bit of 14 is '1', the algorithm is something like:
int j = 128; 128 because this is the number with a '1' in the 8th bit (your 8 bit limit)
int mynumber = 14;
while(j){ // when the j value is 0, it will be the same as false
if(mynumber & j) cout<<1;
else cout<<0;
j=j>>1;
}
Hope you understand, please ensure that your numbers fit in 8 bits (255 max).

Finding denominator which the dividend has the maximum remainder with

I need to find the maximum remainder for n divided by any integer number from 1 to n, and the denominator which this remainder is found with.
In my implementation fun1 works as expected and returns the max remainder, fun2 is supposed to give 3 but its giving 2 .probably mistake is at break statement.
Sample input: 5
Expected output: 2 3.
My output: 2 2.
#include <iostream>
#include <algorithm>
using namespace std;
int fun2(int a);
int fun1(int n ,int num);
int main(){
int n = 0; int num = 0;;
cin >> n;
int p = fun1(n, num);
cout << p << "\n";
cout << fun2(p);
}
int fun1(int n, int num){
int b = 0;
for(int i = 1; i <= n; i++){
num = n % i;
b = max(num, b);
}
return b;
}
int fun2(int n,int p ){
int num = 0; int c = 0; int d = 0;
for(int i = 1; i <= n; i++){
num = n % i;
c = max(num, c);
if(c == p){
break;
}
d = i;
}
return d;
}
Since you already managed to successfully find the biggest remainder, you may get use of this function and return the number this remainder is found with:
std::pair<int, int> biggestRemDem(int value) {
int dm = 1;
int rm = 0;
for(int i = dm; i <= value; ++i){
const auto tmpRm = value % i;
if (tmpRm > rm) {
rm = tmpRm;
dm = i;
}
}
return { rm, dm };
}
The signature of the function needs to return std::pair however, but you no longer need the std::max, so the headers required to include are also changed:
#include <iostream>
#include <utility>
std::pair<int, int> biggestRemDem(int value);
int main(){
int n{};
std::cin >> n;
const auto result = biggestRemDem(n);
std::cout << result.first << " " << result.second << std::endl;
}
In fun2 you have:
if(c == p){
break;
}
d = i;
When you found the right index so that c == p the break will exit the loop and d == i; is not execute. Therefore d has the value from the previous loop, i.e. one less than you need.
Apart from that the code really smells:
fun1
should not have a second argument sum.
should remember the index where if found the largest remainder and you would be done
fun2
the maximum remainder is p, no need to max(num, c). Actually drop the c alltogether and just use num == p
n % 1 == 0 and n % n == 0. The loop will always break with i < n. Might as well not have a conditional: for(int i = 1; ; i++)
you need d because at the end of the loop i disappears. Why not pull i out of the loop? int i; for(i = 1; ; i++)
and now you can use a different conditional again
int fun2(int n,int p ){
int i;
for(i = 1; n % i != p; i++) { }
return i;
}
or
int fun2(int n,int p ){
int i = 1;
for(; n % i != p; i++) { }
return i;
}
or
int fun2(int n,int p ){
int i = 1;
while(n % i != p) ++i;
return i;
}
I need to find the maximum remainder for n divided by any integer number from 1 to n, and the denominator which this remainder is found with.
It seems that the asker decided to solve this in two steps. They wrote a function fun1 returning the maximum remainder and a function fun2, which fed with the previously calculated remainder, returns the corresponding dividend.
While not an efficient approach, it could work if implemented correctly, but that's not the case.
Other than some (very) bad naming choices, we can find:
In the original version of the posted code, fun2 has a function prototype with a single parameter and it is called passing the value returned by fun1, which is the maximum remainder. The problem is that this way the function has no way to know what was the original value of n and actually declares a local n, initialized to zero, so that the body of the loop for(int i = 1; i <= n; i++) is never executed.
The actual version of this question shows a definition of fun2 with two parameters, that can't compile unless both the prototype and the call site are changed accordingly.
Assuming that the original n and the remainder p were succesfully passed to fun2, there still would be another issue:
int fun2(int n, int p ) {
int c = 0, d = 0;
for(int i = 1; i <= n; i++) {
int num = n % i;
c = max(num, c);
if(c == p){ // So, if we reach the passed remainder...
break; // We break out of the loop, skipping...
}
d = i; // this line, meaning...
}
return d; // That the dividend previous to the correct one is returned!
}
They could just return i; when c == p.
The answer by The Dreams Wind presents a much better approach to this task. I'd like to suggest an O(1) solution, though. Consider these points:
The result of n % i can't be equal or greater than i. It's in the range [0, i).
n / 2 is the greatest number that can divide n other than n itself. It means that all the numbers i in (n/2, n) are such that n % i > 0.
For every number i in (n/2, n), we can actually say that n % i = n - i.
So, when n is greater than 2, the i corresponding to the maximum remainder is just 1 + n/2 and said remainder is n - n/2 - 1.

what does int numbers[n+2]; statement do?

#include<iostream>
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
int main() {
int n;
std::cout << "Enter a Number";
std::cin >> n;
int result = fastFibonacci(n);
std::cout << result << "\n";
return 0;
}
in this code when i enter input 0 or 1 get correct answer. But the problem is that when i replace int numbers[n+2]; with the commented part it start giving me wrong answer when input is 0 or 1. why? anyone please explain me.
In this function
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
there is used a variable length array with n + 2 elements declared in this line
int numbers[n+2]; // int numbers[n].
Variable length arrays is not a standard C++ feature. It can be implemented as own language extension of a C++ compiler.
Using the variable length array makes the function very unsafe because there can occur a stack overflow.
As within the function there is explicitly used two elements of the array
numbers[0] = 0;
numbers[1] = 1;
then the array shall have at least two elements even when the parameter has a value less than 2.
To calculate the n-th Fibonacci number there is no need to declare an array of such a size.
Apart from this the function argument shall have an unsigned integer type. Otherwise the function can invoke undefined behavior if the user passes a negative number.
Also for big values of n there can be an integer overflow for the type int.
The function can be implemented in various ways.
Here is one of possible its implementations.
#include <iostream>
#include <functional>
unsigned long long fibonacci( unsigned int n )
{
unsigned long long a[] = { 0, 1 };
while ( n-- )
{
a[1] += std::exchange( a[0], a[1] );
}
return a[0];
}
int main()
{
const unsigned int N = 10;
for ( unsigned int i = 0; i < N; i++ )
{
std::cout << i << ": " << fibonacci( i ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
int numbers[n+2]; is the declaration of an array of ints with space for n + 2 ints, this is a variable lenght array and is not part of C++ standard, though some compilers allow it it's not somenthing you should use.
If you need a variable lenght array use std::vector.
With int numbers[n+2]; if n is equal to 0 you still have space for 2 ints, if you have int numbers[n]; the array will have space for 0 ints, so the code will fail because you are trying to access memory that does not exist with numbers[0] and numbers[1].
There are several good ways to implement the Fibonacci sequence, in the site you can find many questions regarding this matter in several programming languages, here is one of them Fibonacci series in C++
Edit
So I've seen your comments about using a vector, for making the sequence you wouldn't need the vector just two variables to store the two numbers to add, to store the sequence in a vactor, you can do somenthing like:
#include <iostream>
#include <vector>
#include <iomanip>
//passing the vector by reference
void fastFibonacci(unsigned long long n, std::vector<unsigned long long>& sequence) {
unsigned long long first = 0;
unsigned long long second = 1;
sequence.push_back(first); //add first values to the vector
sequence.push_back(second); //add first values to the vector
for (unsigned long long i = 0, value = 0; i < n && value <= LLONG_MAX ; ++i) {
value = first + second;
first = second;
second = value;
sequence.push_back(value); //adding values to the vector
}
}
int main() {
unsigned long long limit; //number of values in the sequence
int num = 1;
std::vector<unsigned long long> sequence; //container for the sequence
std::cout << "Enter upper limit: ";
std::cin >> limit;
fastFibonacci(limit, sequence);
//print the sequence in a range based loop formatted with <iomanip> library
for(auto& i : sequence){
std::cout << std::setw(4) << std::left << num++ << " " << i << std::endl;
}
return 0;
}
If you want to print just one of the numbers in the sequence, just use, for instance:
std::cout << sequence[10];
Instead of the whole vector.
The code you post in the comment to the other answer won't work because the access to the vector is out of bounds in numbers[i] = numbers[i - 1] + numbers[i - 2];, if for instance i = 5, your vector only has 2 nodes but you are accessing the 6th node numbers[5].

Wierd combination

I have an array of 3 integers {1,2,3}. I need to print combinations in the form of-
1 1+2 1+3 1+2+3
2 2+3
3
for(int i = 0; i < array.size(); ++i)
{
for(int j = 0; (i + j) < array.size(); ++j)
{
sum += my[i + j];
cout << sum << " ";
c++;
}
cout << endl;
}
In above, 1+3 is being skipped.
Please help me with that.
Given a set S the power set P(S) is the set of all subsets of S. What you are trying to do is essentially enumerate all of the non-empty elements of x ∈ P(S). From there, you can iterate over all of the elements of each non-empty x in P(S).
What does this mean for you? Well for starters for a set S containing n elements the number of possible elements of P(S) is 2^n, so the size of the power set scales exponentially with the size of its generating set.
But, where this may be useful for small values of n (in particular n < 64) you can use unsigned long long variables to act as a kind of index. In particular, each bit corresponds to one of your array elements. Bits with a value of 0 exclude its associated element in the sum, while bits with a 1 would include the element. To do something like this try the following:
#include <vector>
#include <iostream>
void print_sum(const std::vector<int>& array, unsigned long long i) {
int sum = 0;
for (int index=0; i > 0; i=i>>1, ++index) {
if (i % 2 == 1) {
std::cout << array[index] << (i>1 ? "+" : "=");
sum += array[index];
}
}
std::cout << sum << std::endl;
}
void printer(const std::vector<int>& array) {
if (array.size() < sizeof(unsigned long long) * 8) {
unsigned long long n = 1 << array.size();
for (unsigned long long i = 1; i < n; ++i) {
print_sum(array, i);
}
}
}
int main(int argc, char** argv) {
std::vector<int> sample {1, 2, 3, 4};
printer(sample);
return 0;
}
This program has output:
1=1
2=2
1+2=3
3=3
1+3=4
2+3=5
1+2+3=6
4=4
1+4=5
2+4=6
1+2+4=7
3+4=7
1+3+4=8
2+3+4=9
1+2+3+4=10

Strange loop with size_t

I don't enter the loop using size_t. Why?
If I use int I enter the loop and the output is : 11, 11
int main()
{
int j = 11;
for (size_t i = 11; i > - 1; --j, i -=12)
{
std::cout << i << ", " << j << std::endl;
}
return 0;
}
size_t is typically an unsigned value. In your for loop condition you're saying i > -1. Since i is an unsigned type the -1 is converted to this type, and will have the maximum value for that type.
Because of the promotion you're effectivly comparing 11 (the initial value of i) with the maximum value for size_t and the result is false, thus the loop is never entered.