Why 54 + 400 = 453? - c++

I wanted to convert a string to an integer, and I find the "454" was converted to 453.
I have defined a function which can convert an integer-string to an integer. But when I tested it, I found the "454" was converted to 453. I tried another number 565, and it is correct.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int strtonum(string num){
int i = 0;
int n = 0;
int result=0;
for(i = num.length()-1; i>=0; i--,n++){
if(num[i] == '-'){
result-=2*result;
break;
}
cout<<result<<" + "<<(num[i] - '0')*pow(10,n);
result += (num[i] - '0')*pow(10,n);
cout<<" = "<<result<<endl;
}
return result;
}
int main()
{
string x;
cin>>x;
cout<<strtonum(x)<<endl;
return 0;
}
Result
454
0 + 4 = 4
4 + 50 = 54
54 + 400 = 453
453
Process returned 0 (0x0) execution time : 2.763 s
Press any key to continue.
565
0 + 5 = 5
5 + 60 = 65
65 + 500 = 565
565
Process returned 0 (0x0) execution time : 3.314 s
Press any key to continue.

Your approach involves floating-point computations through your use of the std::pow function.
As you may know, floating-point computations can introduce error. I'm a little surprised to see that here with good wholesome whole numbers, but still you're not dealing with it at all before truncating back to int.
I suggest a different, integer-only manner of raising to a power of ten (perhaps a nice loop!).
Also, as bruno pointed out, this:
result-=2*result;
is overflow-prone and unnecessary when you can just do this instead:
result = -result;
or:
result *= -1;

The usual approach to this is to accumulate values with multiplication by 10:
int convert(std::string text) {
bool negative = false;
int cur = 0;
if (text[cur] == '-') {
negative = true;
++cur;
}
int value = 0;
while (cur < text.length()) {
value *= 10;
value += text[cur++] - '0';
}
if (negative)
value = -value;
return value;
}
Note: this code has not been tested. It might contain errors.

Related

why for loop is not work correctly for a simple multiplication numbers 1 to 50?

code:
#include <iostream>
using namespace std;
int main() {
int answer = 1;
int i = 1;
for (; i <= 50; i++){
answer = answer * i;
}
cout << answer << endl;
return 0;
}
resault :
0
...Program finished with exit code 0
Press ENTER to exit console.
when i run this code in an online c++ compiler, it shows me zero(0) in console. why?
I will answer specifically the asked question "Why?" and not the one added in the comments "How?".
You get the result 0 because one of the intermediate values of answer is 0 and multiplying anything with it will stay 0.
Here are the intermediate values (I found them by moving your output into the loop.):
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
1932053504
1278945280
2004310016
2004189184
-288522240
-898433024
109641728
-2102132736
-1195114496
-522715136
862453760
-775946240
2076180480
-1853882368
1484783616
-1375731712
-1241513984
1409286144
738197504
-2147483648
-2147483648
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
E.g. here https://www.tutorialspoint.com/compile_cpp_online.php
Now to explain why one of them is 0 to begin with:
Because of the values, the sequence of faculties, quickly leaves the value range representable in the chosen data type (note that the number decimal digits does not increase at some point; though the binary digits are the relevant ones).
After that, the values are not really related to the correct values anymore, see them even jumping below zero and back...
... and one of them happens to be 0.
For the "How?" please see the comments (and maybe other, valuable answers).
Short Answer:
Your code is not working correctly because it performs 50 factorial, that the answer is 3.04*10^64. This number is greater than the int size, that is 2^31 - 1.
Long answer
You can check the problem logging the intermediate answers. This can help you to have some insights about the code situation. Here you can see that the number rotate from positive to negative, that's show the maximum possible multiplication with this code strategy.
https://onlinegdb.com/ycnNADKmX
The answer
30414093201713378043612608166064768844377641568960512000000000000
To archive the correct answer to any case of factorial, you need to have some strategy to operate to large numbers.
In fact, if you're working a large company, you probably have some library to work with large numbers. In this situation, is very important use this library to keep the code consistent.
In other hand, supposing that's an academic homework, you can choose any strategy in the Internet. In this situation I used the strategy that uses string to represent large numbers. You can see the solution here https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings
The final program that compute the 50! in the proper manner using the string strategy to represent large numbers you can find here https://onlinegdb.com/XRL9akYKb
PS: I'll put the complete answer here to archive the code for future references.
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
//#see https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/
// Multiplies str1 and str2, and prints result.
string multiply(string num1, string num2)
{
int len1 = num1.size();
int len2 = num2.size();
if (len1 == 0 || len2 == 0)
return "0";
// will keep the result number in vector
// in reverse order
vector<int> result(len1 + len2, 0);
// Below two indexes are used to find positions
// in result.
int i_n1 = 0;
int i_n2 = 0;
// Go from right to left in num1
for (int i=len1-1; i>=0; i--)
{
int carry = 0;
int n1 = num1[i] - '0';
// To shift position to left after every
// multiplication of a digit in num2
i_n2 = 0;
// Go from right to left in num2
for (int j=len2-1; j>=0; j--)
{
// Take current digit of second number
int n2 = num2[j] - '0';
// Multiply with current digit of first number
// and add result to previously stored result
// at current position.
int sum = n1*n2 + result[i_n1 + i_n2] + carry;
// Carry for next iteration
carry = sum/10;
// Store result
result[i_n1 + i_n2] = sum % 10;
i_n2++;
}
// store carry in next cell
if (carry > 0)
result[i_n1 + i_n2] += carry;
// To shift position to left after every
// multiplication of a digit in num1.
i_n1++;
}
// ignore '0's from the right
int i = result.size() - 1;
while (i>=0 && result[i] == 0)
i--;
// If all were '0's - means either both or
// one of num1 or num2 were '0'
if (i == -1)
return "0";
// generate the result string
string s = "";
while (i >= 0)
s += std::to_string(result[i--]);
return s;
}
// Calculates the factorial of an inputed number
string fact(int in) {
string answer = "1";
for (int i = 2 ; i <= in; i++) {
string tmp = std::to_string(i);
answer = multiply(answer, tmp);
}
return answer;
}
int main()
{
string answer = fact(50);
cout << answer << endl;
return 0;
}

my value is more than the range of unsigned integer

i have this exercise:" consider some natural number n, if it is not a Palindrom number, change the order of the digits in reverse order and add the resulting number with the original number. If the sum is not a palindrom number, repeat the same procedure on that sum until a palindrom number is obtained. Whether the above process is finite for any n. If yes, print out the number of process "
ex
input:1 output: 0
input: 12 output: 1
my problem is when i encounter larger number such as 19170 it will be over the limit of unsigned long long int
It will also be great if anyone can explain or guide me to resources that can help me understand it further.
#include <iostream>
#include <math.h>
using namespace std;
bool check (long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
if(ans==n)
{
return true;
}
return false;
}
long long int reverse(long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
return ans;
}
int main()
{
long long int n,count=0;
cin>>n;
if(check(n))
{
cout<<0;
return 0;
}
else
{
while(check(n)!=1)
{
count++;
n+=reverse(n);
}
}
cout<<count;
}
my code is also included in the link: https://ideone.com/0p7JJU
The natural number that will not terminate the algorithm that the OP describe is called Lychrel number. https://en.wikipedia.org/wiki/Lychrel_number
It is currently unknown if any of these number exists, as correctly guessed by zkoza in the above answer, 196 is the smallest candidate to be a Lychrel number.
So, this is a specifically hard problem to tackle, however, I would like to address the specific overflow issue that the OP is facing. As pointed out by largest_prime_is_463035818 in the comments, there is no actual needs of any integer representation.
#include <iostream>
//take advantage of the fact that std::string use contiguous memory
bool is_palindrome(const char* first, const char* last)
{
--last;
while(first < last) {
if (*first != *last)
return false;
++first;
--last;
}
return true;
}
std::string reverse_and_add(const std::string& digits)
{
size_t size = digits.size();
//the result string will be at least the same length
std::string result(size,'0');
int carry_over = 0;
int ascii_zero = 48;
for (size_t i = 0; i < size; i++)
{
int front = digits.at(i) - ascii_zero;
int back = digits.at(size - i - 1) - ascii_zero;
int sum = front + back + carry_over;
carry_over = sum / 10;
int digit = sum >= 10 ? sum - 10 : sum;
result[size - i - 1] = static_cast<char>(digit + ascii_zero);
}
//if at the last step we have a carry over we need to add an extra digit to
//the string
if (carry_over > 0)
result = static_cast<char>(carry_over + ascii_zero) + result;
return result;
}
void check(const std::string& s, int max_iteration)
{
int counter = 0;
std::string v(s);
while(!is_palindrome(v.c_str(), v.c_str() + v.size()) && counter < max_iteration)
{
v = reverse_and_add(v);
if (counter % 1000 == 0 && counter > 0)
std::cout << "progressing iteration: " << counter << " string size: " << v.size() << std::endl;
counter++;
}
if (counter == max_iteration)
std::cout << "No result found" << std::endl;
else
std::cout << "result: " << counter << std::endl;
}
int main()
{
int max_iteration = 50000;
check("187",max_iteration); // -> return 23
check("19170", max_iteration); // -> doesn't find a solution
// the final string is thousands of characters
}
UPDATE
Just for fun, I run 196 till 1000000 digits (that it took 3 years to complete 1987) and it produce the same result in about an hour and half (these hardware engineers are amazing).
result: 2415836
./a.out 5315.83s user 21.29s system 99% cpu 1:29:12.58 total
I assume this is a homework question.
The first number for which the sequence does not seem to be finite is as small as 196. I terminated a program after it hit 300000 digits.
What can you do?
Write a similar program where you implement your own "big numbers". It's an easy task, because all you need is addition of two same-length numbers, reversal, checking for being a palindrom, perhaps printing. You can use std::vector or std::string.
Then, introduce an ad hoc threshold, like 100 or 1000 iterations. If the sequence will reach the threshold, stop it and return false.
It is possible that you did not present here the complete, detailed description of the problem. I found a similar problem on the internet, but with an explicit threshold of 5 iterations. Or perhaps it is a problem that you've invented yourself, unaware of its complexity? Or the teacher is pulling your leg? Or I made a mistake in my code.
A famous example of a problem that has a simple formulation but no known solution is the Collatz conjecture, https://en.wikipedia.org/wiki/Collatz_conjecture . It can't be ruled out that your problem is of a similar type.
Here, for reference, is my solution for numbers from 180 to 195 (the first number in the sequence, the number of iteration, the last number in the sequence)
180 3 747
181 0 181
182 6 45254
183 4 13431
184 3 2552
185 3 4774
186 3 6996
187 23 8813200023188
188 7 233332
189 2 1881
190 7 45254
191 0 191
192 4 6996
193 8 233332
194 3 2992
195 4 9339
Instead of numeric data type you can use string to store the values and do addition by parsing the whole string like this
#include <iostream>
#include <string>
int main()
{
std::string s1 = "759579537575937593759387";
std::string s2 = "9956775659653876536535637653";
int n1=s1.size()-1,n2=s2.size()-1;
std::string s3 = "";
uint8_t carry = 0;
while(n1>=0 && n2>=0){
uint8_t num1 = (int)s1[n1--] - 48;
uint8_t num2 = (int)s2[n2--] - 48;
uint8_t sum = char(num1+num2) + carry;
carry = sum/10; // to get carry
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n1>=0)
{
uint8_t sum = carry + (int)s1[n1--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n2>=0)
{
uint8_t sum = carry + (int)s2[n2--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
if (carry)
s3.insert(0,1,char(carry+48));
std::cout<<s3<<std::endl;
}
also you check if they are palindromic or not using two pointer method.
The above sum which I get is 9957535239191452474129397040, there is no limit to addition by this method

Why is 1 * 4 = 196?

Im trying to make a binary converter, the problem however is that when I build it, it usually decrypts my test number "101" which should be 5 into something along the lines of 300 - 3000.
int main()
{
char a;
string bintered;
int bincrypted = 0, bincrypter;
cout<<"Would you like to try the binary to decimal converter? Y/N"<<endl;
cin>>a;
if (a == 'Y' || a == 'y')
{
cout<<"Ok, enter a binary number and we will decrypt it > ";
cin>>bintered;
int x = bintered.length() - 1; //multiplier counting down
int y = 0;
int power = 0;
while (x != -1)
{
power = bintered[y] * pow(2.0, x);
bincrypted = bincrypted + power;
y++;
x = x - 1;
}
cout<<"Final answer is: "<<bincrypted<<endl;
}
return 0;
}
When I tried doing cout<<bintered[y] * pow(2.0, x); it gave me 196, 96 and 49 for the three loops it did.
Am i using the pow function incorrectly or what?
bintered[y] returns the ascii code of the character, so 48 for 0 and 49 for 1.

Armstrong numbers. print armstrong numbers

I kindly request those who think this question have been asked earlier, read on first.
I need to print all armstrong numbers between 1 and 10000. My problem is that whenever my program is run and reaches 150, it does
(1^3) + ((5^3)-1) + (0^3)
instead of
(1^3) + (5^3) + (0^3).
Thus it does not print 153 (which is an Armstrong number), of course because the sum results in 152. I do not know if some other numbers are also doing this. But i do have checked untill 200 and there is no problem with other numbers except that in 150–160 range.
Is this a compiler error. Should i re-install my compiler? Currently i am using codeblocks.
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
for(int i = 0;i <= 10000;++i)
{
int r = i;
int dig = 0;
while(r != 0)
{
dig++;
r /= 10;
}
int n = i, sum = 0;
while(n != 0)
{
int d = n % 10;
sum += pow(d, dig);
n /= 10;
}
if(sum == i)
cout << i << ' ';
}
cout << "\n\n\n";
return 0;
}
You should run your code in the debugger. Also your code does not compile for me (GCC 6) because you use cout without std:: or using namespace std;. So how does it compile on your system? You are also using math.h, in C++ you should rather use cmath.
After fixing this, I get the following output on my Fedora 24 with g++ in version 6.4.1:
0 1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
The 153 is included in there, so either your compiler has an error or your program has undefined behavior and therefore the error ensues.
I have looked at the definition for Armstrong numbers and did a really short Python implementation:
# Copyright © 2017 Martin Ueding <dev#martin-ueding.de>
# Licensed under the MIT/Expat license.
def is_armstrong(number):
digits = [int(letter) for letter in str(number)]
score = sum(digit**len(digits) for digit in digits)
return score == number
armstrong = list(filter(is_armstrong, range(10000)))
print(' '.join(map(str, armstrong)))
The output matches your C++ program on my machine exactly:
0 1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
Looking through your code I cannot spot undefined behavior, it looks sensible. First you count the number of digits, then you build up the sum. Perhaps you should try with other compilers like GCC, LLVM, or Ideone. Does Code Blocks ship their own compiler or do they use a system compiler? What operating system are you running?
You said that you are just learning to program. That's cool to hear! I hope you have a good C++ book or other resource. For C++, there is a lot of bad advice on the internet. Also make sure that you have a book that has at least C++11, everything else is badly outdated.
I have changed your program and created some short functions that do just one task such that it is easier to read and reason about. I am not sure whether you already know about functions, so don't worry if that seems to complicated for now :-).
#include <cmath>
#include <iostream>
int get_digit_count(int const number) {
int digits = 0;
int remainder = number;
while (remainder > 0) {
++digits;
remainder /= 10;
}
return digits;
}
bool is_armstrong_number(int const number) {
int const digit_count = get_digit_count(number);
int remainder = number;
int sum = 0;
while (remainder > 0) {
int const last_digit = remainder % 10;
sum += std::pow(last_digit, digit_count);
remainder /= 10;
}
return number == sum;
}
int main() {
for (int i = 0; i <= 10000; ++i) {
if (is_armstrong_number(i)) {
std::cout << i << ' ';
}
}
std::cout << std::endl;
}
This algorithm generates and prints out Armstrong numbers to 999, but can easily be expanded to any length using the same methodology.
n = 1; %initialize n, the global loop counter, to 1
for i = 1 : 10 %start i loop
for j = 1 : 10 %start j loop
for k = 1 : 10 %start k loop
rightnum = mod(n, 10); %isolate rightmost digit
midnum = mod(fix((n/10)), 10); %isolate middle digit
leftnum = fix(n/100); %isolate leftmost digit
if ((n < 10)) %calulate an for single-digit n's
an = rightnum;
end
if ((n > 9) & (n < 100)) %calculate an for 2-digit n's
an = fix(rightnum^2 + midnum^2);
end
if ((n > 99) & (n < 1000)) %calculate an for 3-digit n's
an = fix(leftnum^3 + midnum^3 + rightnum^3);
end
if (n == an) %if n = an display n and an
armstrongmatrix = [n an];
disp(armstrongmatrix);
end
n = n + 1; %increment the global loop counter and continue
end
end
end
You can use arrays:
#include<iostream>
using namespace std;
int pow(int, int);
int checkArm(int);
int main() {
int range;
cout<<"Enter the limit: ";
cin>>range;
for(int i{};i<=range;i++){
if(checkArm(i))
cout<<i<<endl;
}
return 0;
}
int pow(int base, int exp){
int i{0};
int temp{base};
if(exp!=0)
for(i;i<exp-1;i++)
base = base * temp;
else
base=1;
return base;
}
int checkArm(int num) {
int ar[10], ctr{0};
int tempDigits{num};
while(tempDigits>0){
tempDigits/=10;
ctr++;
}
int tempArr{num}, tempCtr{ctr};
for(int i{0};i<=ctr;i++){
ar[i] = tempArr / pow(10,tempCtr-1);
tempArr = tempArr % pow(10,tempCtr-1);
tempCtr--;
}
int sum{};
for(int k{};k<ctr;k++){
sum+=pow(ar[k],ctr);
}
if(sum==num)
return 1;
else
return 0;
}

Is this an inefficent way to convert from a binary string to decimal value?

while(i < length)
{
pow = 1;
for(int j = 0; j < 8; j++, pow *=2)
{
ch += (str[j] - 48) * pow;
}
str = str.substr(8);
i+=8;
cout << ch;
ch = 0;
}
This seems to be slowing my program down a lot. Is it because of the string functions I'm using in there, or is this approach wrong in general. I know there's the way where you implement long division, but I wanted to see if that was actually more efficient than this method. I can't think of another way that doesn't use the same general algorithm, so maybe it's just my implementation that is the problem.
Perhaps you want might to look into using the standard library functions. They're probably at least as optimised as anything you run through the compiler:
#include <iostream>
#include <iomanip>
#include <cstdlib>
int main (void) {
const char *str = "10100101";
// Use str.c_str() if it's a real C++ string.
long int li = std::strtol (str, 0, 2);
std::cout
<< "binary string = " << str
<< ", decimal = " << li
<< ", hex = " << std::setbase (16) << li
<< '\n';
return 0;
}
The output is:
binary string = 10100101, decimal = 165, hex = a5
You are doing some things unnecessarily, like creating a new substring for each each loop. You could just use str[i + j] instead.
It is also not necessary to multiply 0 or 1 with the power. Just use an if-statement.
while(i < length)
{
pow = 1;
for(int j = 0; j < 8; j++, pow *=2)
{
if (str[i + j] == '1')
ch += pow;
}
i+=8;
cout << ch;
ch = 0;
}
This will at least run a bit faster.
short answer could be:
long int x = strtol(your_binary_c++_string.c_str(),(char **)NULL,2)
Probably you can use int or long int like below:
Just traverse the binary number step by step, starting from 0 to n-1, where n is the most significant bit(MSB) ,
multiply them with 2 with raising powers and add the sum together. E.g to convert 1000(which is binary equivalent of 8), just do the following
1 0 0 0 ==> going from right to left
0 x 2^0 = 0
0 x 2^1 = 0;
0 x 2^2 = 0;
1 x 2^3 = 8;
now add them together i.e 0+0+0+8 = 8; this the decimal equivalent of 1000. Please read the program below to have a better understanding how the concept
work. Note : The program works only for 16-bit binary numbers(non-floating) or less. Leave a comment if anything is not clear. You are bound to receive a reply.
// Program to convert binary to its decimal equivalent
#include <iostream>
#include <math.h>
int main()
{
int x;
int i=0,sum = 0;
// prompts the user to input a 16-bit binary number
std::cout<<" Enter the binary number (16-bit) : ";
std::cin>>x;
while ( i != 16 ) // runs 16 times
{
sum += (x%10) * pow(2,i);
x = x/10;
i++;
}
std::cout<<"\n The decimal equivalent is : "<<sum;
return 0;
}
How about something like:
int binstring_to_int(const std::string &str)
{
// 16 bits are 16 characters, but -1 since bits are numbered 0 to 15
std::string::size_type bitnum = str.length() - 1;
int value = 0;
for (auto ch : str)
{
value |= (ch == '1') << bitnum--;
}
return value;
}
It's the simplest I can think of. Note that this uses the new C++11 for-each loop construct, if your compiler can't handle it you can use
for (std::string::const_iterator i = str.begin(); i != str.end(); i++)
{
char ch = *i;
// ...
}
Minimize the number of operations and don't compute things more than once. Just multiply and move up:
unsigned int result = 0;
for (char * p = str; *p != 0; ++p)
{
result *= 2;
result += (*p - '0'); // this is either 0 or 1
}
The scheme is readily generalized to any base < 10.