I made a little program to determine the length of a user-provided integer:
#include <iostream>
using namespace std;
int main()
{
int c=0; //counter for loop
int q=1; //quotient of number upon division
cout << "Hello Cerberus! Please enter a number." << endl;
cin >> q;
if(q > -10 && q < 10)
{
cout << "The number you entered is 1 digit long." << endl;
}
else
{
while(q != 0)
{
q=q/10;
c++;
}
cout << "The number you entered is " << c << " digits long." << endl;
}
return 0;
}
It works quite nicely, unless the numbers get too big. Once the input is 13 digits long or so, the program defaults to "The number you entered is 1 digit long" (it shouldn't even present that solution unless the number is between -10 and 10).
Is there a length limit for user-input integers, or is this demonstrative of my computer's memory limits?
It's a limit in your computer's architecture. Every numeric type has a fixed upper limit, because the type describes data with a fixed size. For example, your int is likely to take up either four or eight bytes in memory (depending on CPU; based on your observations, I'd say the former), and there are only so many combinations of bits that can be stored in so many bytes of memory.
You can determine the range of int on your platform using std::numeric_limits, but personally I recommend sticking with the fixed-width type aliases (e.g. int32_t, int64_t) and picking whichever ones have sufficient range for your application.
Alternatively, there do exist so-called "bigint" libraries that are essentially classes wrapping integer arrays and adding clever functionality to make arbitrarily-large values work as if they were of arithmetic types. That's probably overkill for you here though.
Just don't be tempted to start using floating-point types (float, double) for their magic range-enhancing abilities; just like with the integral types, their precision is fundamentally limited, but using floating-point types adds additional problems and concerns on top.
There is no fundamental limit on user input, though. That's because your stream is converting text characters, and your stream can basically have as many text characters in it as you could possibly imagine. At that level, you're really only limited by available memory.
Related
Alright so, I'm a noob first of all. I started studying code (in C++), and I want to make a random number generator. It's great and all, but as far as I've observed, the generated numbers never exceed the "int" limit of 32768, even tho my variables are all "unsigned long long" (I'm pretty sure that's how you get the largest pool of numbers). I'm pretty sure it's something small, but it;s been bothering me for a day, and I really need answers.
Here's how my current code looks like :
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
unsigned long long n,m,r,mx;
cout<< "Please Enter The Number Of Desired Randomly Generated Numbers : ";
cin>>m;
cout<< "Please Enter An Upper Limit to the Random Numbers : " ;
cin>>mx;
srand ( time(NULL) );
for (int i=1; i<=m ; i++)
{
n = rand() % mx;
cout << n << endl;
}
cout<< "Rate this Program Out Of 10: ";
cin >> r;
cout << r << " " << "/" << "10";
return 0;
}
Even though all the numbers you use are unsigned long long, rand() will only ever return a number less than or equal to RAND_MAX which is guaranteed to be 32767 or more.
To guarantee a return value more than 32767 you're going to need some more advanced random number generation techniques. The standard library has a module for this called random.
Take a look at the uniform_int_distribution object. That page gives an example of how to use it to generate regular integers however the object does take a template parameter that allows you to specify what kind of integer is returned.
In your case you would want to use:
std::uniform_int_distribution<unsigned long long>
Using that in the example on the page will generate 10 unsigned long long numbers (however if you copy the example exactly they will still be limited to between 1 and 6).
I'm trying to write a program that uses the series to compute the value of PI. The user will input how far it wants the program to compute the series and then the program should output its calculated value of PI. I believe I've successfully written the code for this, however it does not do well with large numbers and only gives me a few decimal places. When I tried to use cout << fixed << setprecision(42); It just gave me "nan" as the value of PI.
int main() {
long long seqNum; // sequence number users will input
long double val; // the series output
cout << "Welcome to the compute PI program." << endl; // welcome message
cout << "Please inter the sequence number in the form of an integer." << endl;
cin >> seqNum; // user input
while ( seqNum < 0) // validation, number must be positive
{
cout << "Please enter a positive number." << endl;
cin >> seqNum;
} // end while
if (seqNum > 0)
{
for ( long int i = 0; i < seqNum; i++ )
{
val = val + 4*(pow(-1.00,i)/(1 + 2*i)); // Gregory-Leibniz sum calculation
}// end for
cout << val;
} // end if
return 0;
}
Any help would be really appreciated. Thank you
Your problem involves an elementary, fundamental principle related to double values: a double, or any floating point type, can hold only a fixed upper limit of significant digits. There is no unlimited digits of precision with plain, garden-variety doubles. There's a hard, upper limit. The exact limit is implementation defined, but on modern C++ implementations the typical limit is just 16 or 17 digits of precision, not even close to your desired 42 digits of precision.
#include <limits>
#include <iostream>
int main()
{
std::cout << std::numeric_limits<double>::max_digits10 << std::endl;
return 0;
}
This gives you the maximum digits of precision with your platform/C++ compiler. This shows a maximum of 17 digits of precision with g++ 9.2 on Linux (max_digits10 is C++11 or later, use digits10 with old C++ compilers to show a closely-related metric).
Your desired 42 digits of precision likely far exceed what your modest doubles can handle. There are various special-purpose math libraries that can perform calculations with higher levels of precision, you can investigate those, if you wish.
You did not initialize or assign any value to val, but you are reading it when you get to the first iteration of
val = val + 4*(pow(-1.00,i)/(1 + 2*i));
This cause your program to have undefined behavior. Initialize val, probably to zero:
long double val = 0; // the series output
That aside, as mentioned in the answer of #SamVarshavchik there is a hard limit on the precision you can reach with the built-in floating point types and 42 places significance is almost certainly outside of that. Similarly the integer types that you are using are limited in size to probably at most 2^64 which is approximately 10^19.
Even if these limits weren't the problem, the series requires summation of roughly 10^42 terms to get PI to a precision of 42 places. It would take you longer than the universe has been around to calculate to that precision with all of earths current computing power combined.
How long double fits so many characters in just 12 bytes?
I made an example, a C ++ factorial
when entering a large number, 1754 for example it calculates with a number that apparently would not fit a long double type.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
unsigned int n;
long double fatorial = 1;
cout << "Enter number: ";
cin >> n;
for(int i = 1; i <=n; ++i)
{
fatorial *= i;
}
string s = to_string(fatorial);
cout << "Factorial of " << n << " = " <<fatorial << " = " << s;
return 0;
}
Important note:
GCC Compiler on Windows, by visual Studio long double behaves like a double
The problem is how is it stored or the to_string function?
std::to_string(factorial) will return a string containing the same result as std::sprintf(buf, "%Lf", value).
In turn, %Lf prints the entire integer part of a long double, a period and 6 decimal digits of the fractional part.
Since factorial is a very large number, you end up with a very long string.
However, note that this has nothing to do with long double. A simpler example with e.g. double is:
#include <iostream>
#include <string>
int main()
{
std::cout << std::to_string(1e300) << '\n';
return 0;
}
This will print:
10000000000000000525047602 [...300 decimal digits...] 540160.000000
The decimal digits are not exactly zero because the number is not exactly 1e300 but the closest to it that can be represented in the floating-point type.
It doesn't fit that many characters. Rather, to_string produces that many characters from the data.
Here is a toy program:
std::string my_to_string( bool b ) {
if (b)
return "This is a string that never ends, it goes on and on my friend, some people started typing it not knowing what it was, and now they still are typing it it just because this is the string that never ends, it goes on and on my friend, some people started typing it not knowing what it was, and now they still are typing it just because...";
else
return "no it isn't, I can see the end right ^ there";
}
bool stores exactly 1 bit of data. But the string it produces from calling my_to_string can be as long as you want.
double's to_string is like that. It generates far more characters than there is "information" in the double.
This is because it is encoded as a base 10 number on output. Inside the double, it is encoded as a combination of an unsigned number, a sign bit, and an exponential part.
The "value" is then roughly "1+number/2^constant", times +/- one for the sign, times "2^exponential part".
There are only a certain number of "bits of precision" in base 2; if you printed it in base 2 (or hex, or any power-of-2 base) the double would have a few non-zero digits, then a pile of 0s afterwards (or, if small, it would have 0.0000...000 then a handful of non-zero digits).
But when converted to base 10 there isn't a pile of zero digits in it.
Take 0b10000000 -- aka 2^8. This is 256 in base 10 -- it has no trailing 0s at all!
This is because floating point numbers only store an approximation of the actual value. If you look at the actual exact value of 1754! you'll see that your result becomes completely different after the first ~18 digits. The digits after that are just the result of writing (a multiple of) a large power of two in decimal.
I am trying to learn how to program in C++, so I created something that allowed to you enter a minimum, and maximum parameter, and it will compute k+(k+1)+(k+2)+...+(max), and compared it to the analytical value, using the standard formula (n(n+1)/2). It seems to work fine when I try small numbers, but when, for example, trying min=4, max=4*10^5 (400,000), I get a negative result for the sum, but a positive result checking with the analytical method, even after changing the type from 'int' to 'long'. Trying other combinations, I have achieved the opposite, with the analytical method resulting in a negative sum. I suspect this is related to the fact the type int can go up to a certain number of digits, but I wanted some confirmation on that, and if it isn't, what the actual problem is. The code is provided below:
#include <iostream>
// Values are inconsistent when paramin,parammax become large.
// For example, try (parammin,parammax)=(4,400,000)
int main() {
int parammax,parammin;
std::cout << "Input a minimum, then maximum parameter to sum up to" << std::endl;
std::cin >> parammin >> parammax;
int sum=0;
for (int iter = parammin; iter <= parammax; iter++){
sum += iter;
}
std::cout << "The sum is: " << sum << std::endl;
const int analyticalmethod = (parammax*(parammax+1)-parammin*(parammin-1))/2;
std::cout << "The analytical result for the sum is,"
" via (max*(max+1)-min*(min-1))/2: "
<< analyticalmethod << std::endl;
return 0;
}
Using very large numbers without control is dangerous in C++. The basic types int, long and long long are implementation dependant, with only the following requirements:
int is at least 16 bits large
long is at least as large as int and at least 32 bits large
long long is at least as large as long and at least 64 bits large
If you think you can need larger values, you should considere a multi precision library like the excellent gmp.
So I wrote this small application that will convert a decimal to octal, and it is outputting the right answer only it's backwards. An example would be that if the answer to the conversion was 17, the application would display it as 71.
Any help would be much appreciated.
;
int _tmain(int argc, _TCHAR* argv[])
{
int octal, total = 0;
cout<< "please enter a decimal: ";
cin >> octal;
while(octal > 0)
{
total = octal % 8;
octal /= 8;
cout << total;
}
cout << endl;
_getche();
return 0;
}
You can use std::oct to print number in octal notation.
int n = 123;
std::cout << std::oct << n << std::endl;
Similarly you can print number in different notations like decimal - std::dec and hexadecimal - std::hex.
Those input/output manipulators allow user to parse string numbers in various notations.
int n;
std::istringstream("24") >> std::hex >> n;
std::cout << n << std::endl; // n is 36 (decimal)
You need to take a sum and then print the final result, something like
int n=0;
while (octal > 0) {
total += (pow(10,n++))*(octal % 8);
octal /= 8;
}
cout << total << endl;
Just printing the digits will print them in reverse order since you are printing the smallest bits first.
As noted in the comments, the mechanism above will only work for converting to bases smaller than 10.
You are doing fine but you have to print the remainders in reverse order to get the correct answer . For e.g. if ans is 17 then decimal equivalent will be 1*8^1+7*8^0 . unit digit will be the remainder obtained by dividing the number by 8 , next digit to the left will be the remainder obtained by dividing the number by 8^2 and so on. So if the number in octal is of n digit then the most significant digit will be the remainder obtained by dividing the number by 8^n.That is why you have to print the remainder in reverse order.
A solution using an array for temporary storage:
int octal, total = 0, length=0;
char storage[12]; /* 11 octal digits add up to > 1 billion */
octal = 123;
while (octal > 0)
{
storage[length] = octal % 8;
octal /= 8;
length++;
}
while (--length >= 0)
printf ("%d", storage[length]);
printf ("\n");
(I happened to be in C mode, hence the printfs. Change to cout where required.)
The most important point is that you are bound by the storage size. You can set it to a reasonable size -- the largest positive octal size you can put in an integer is 017777777777 --, and even an unreasonable size is acceptable (you can set it to 20, which will only waste 8 additional bytes; these days, that's nothing). The storage size is determined by how big the representation of your number is in octal, for the largest number you can enter.
Suppose you change both 8s to 2; then you can use this same routine for binary output. But at that point, the number of output characters increases to 31! (One less than the [likely] number of bits in your int, because the last bit would toggle the number to negative. You need separate code to handle negative numbers.)
It works as-is for all bases <=10 (including "base 10" itself). If you want to extend the same code to handle bases >10, such as "duodecimal" (base 12) or hexadecimal (base 16), you need to change the printf line. This will make your code work up to base 36 ("sexatrigesimal"). Per convention, "digits" higher than 9 are written A,B,C and so on:
while (--length >= 0)
printf ("%c", storage[length] < 10 ? storage[length]+'0' : storage[length]+'A'-10);
(As I'm making this up as I write, I used the ternary operator ?..:.. for convenience, rather than a separate if..else, which needs more typing. (OTOH, adding the comment negates the gain. Oh well -- at least you learned about the ternary operator, as well as the names for a couple of number bases.))
Another solution is to use recursion. This is a useful method because it doesn't need to preallocate some space in memory -- instead, it relies on the internal call stack.
The principle is that you write a function that only prints the last digit of your number -- but before it does that, unless the remainder is 0, it calls itself with the remainder of the number.
So the function calls itself, then prints the number it should. Because it first calls itself, the called version prints the number it should -- the one to the left of the digit in the "original" function. And so on and so forth, until there is no digit remaining to be printed. From that point on, the last called function prints its number (which is the leftmost digit), returns to the function it was called from, which in turn prints its number (one more to the right), all the way down to the original call.
Recursion is a pretty cool skill to master, so do try this!
Here are two handy functions which might be useful. They return string for each of the conversions. On similar lines to igleyy's answer.
string toOctalFromDecimal (int num) {
ostringstream o;
o << std::oct << num;
return o.str();
}
string toDecimalFromOctal (int num) {
std::ostringstream o;
int x;
std::istringstream(to_string(num)) >> std::oct >> x;
o << std::dec << x;
return o.str();
}