Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
inline int input()
{
int c;
int n = 0;
while ((c = getchar_unlocked()) >= '0' && c <= '9')
{
// n = 10 * n + (c - '0');
n = (n << 3) + ( n << 1 ) + c - '0';
}
return n;
}
Can someone explain how this way of inputting the number is working and how it is the fast way to input a number?
Compilers are generally very stupid, and have no understanding of the logic you're trying to implement. Moreover, they're often written by less-than-competent people who don't understand much of modern hardware.
The author of the code has realized this, and cleverly analyzed that 10 is the same as 8 + 2, and that 8 and 2 are both powers of two. For the flourish, he proceeded to turn the mathematics of exponentials into native, bitwise hardware instructions. This combination of mathematics and deep understanding of the hardware leads him to factor 10 * x as 8 * x + 2 * x and express the result in terms of instructions that are far more optimal than the naive "stupid multiplication" that would otherwise have taken place. Naturally, such optimizations are far beyond the reach of any kind of technology and cannot possibly be performed automatically.
The result is a vastly improved method of multiplying a number by ten.
Patent pending.
n << 3 equals n * 8
n << 1 equals n * 2
i.e. (n << 3) + ( n << 1 ) equals 10 * n
bitwise shift is faster than multiplication, though I'm not sure the whole thing should be faster.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to know about what is the use of that (index & 0x01) in the code?
if(((arr[index] >= 0) && (!(index & 0x01)))
|| ((arr[index] < 0) && (index & 0x01)))
{
outofplace = index;
}
A number is odd if and only if its last digit is odd, regardless of the base. So if we want to know the number's oddity, it's enough to check if the last bit is set.
index & 0x01
will be 1 if and only if index is odd.
If we have to deduce a general rule, we can say that for any non-negative number x,
x % y == (x & (y - 1))
provided that y is a positive power of 2.
This is a common hack in competitive coding. It is used because the competitive programmers think that bit-wise AND works faster than modulo.
In modern compilers, there is no performance difference at all. Read this thread.
There is no special reason in writing it as 0x01 instead of 1. Both compile to give the same assembly! Almost everyone (who uses this hack),= uses 1, because we have to type 3 characters extra in 0x01. :P
Here in this case, index & 0x1 is equivalent to index % 2 which is simply a condition to check if the number is odd. (Array indexes in C++ are always positive, unless you are going out of bound.)
As the other answers pointed out, while this is a well known pattern (see also this Q&A about that mask), it can be considered a premature optimization.
I'd like to suggest the following alternative to the posted code, which I find more readable. Your mileage may vary.
// Give a meaningful name.
constexpr auto is_odd = [] (auto x) -> bool {
return x % 2;
}
// Use it to simplify the condition.
if ( (arr[index] < 0) == is_odd(index) ) {
// Do something
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I was trying to make a C++ program to calculate value of Pi up to 'n' decimal places using the Leibniz formula.
The number 'n' would be entered by the user.
I was successful in creating the Leibniz formula but I am having trouble with the latter part i.e value precise up to 'n' places.
The trouble :-
As more and more terms will continue to add to it, it's digits will keep on changing so how to tell if a particular digit has stopped changing despite the addition of more terms.
The code written so far :-
#include<iostream>
using namespace std;
int main()
{
float s=0;
int w=-1;
for(float i=1;;i=i+2)
{
w=w*(-1);
s=s+w*(1/i);
cout<<s<<endl;
}
return 0;
}
It would be great if things would be kept simple since I am just a beginner at C++.
Thank you very much :)
Since you want to compute Pi up to arbitrary nth digit, you want a library for working with big float numbers; see
C++ library for big float numbers
the real trouble is that Leibniz formula is not useful in the context. The actual precision achieved can be estimated as the last term in the formula
Pi / 4 = 1/1 - 1/3 + 1/5 - 1/7 + ... + (-1)**(n + 1) * 1 / (2 * n - 1) + ...
If, for intance, you want Pi up to 100th digit it means that the residual (and the last term) should be less than 1e-100:
1 / (2 * n - 1) < 1e-100
2 * n - 1 > 1e100
n > 5e99
And as you can see 5e99 loops is by far too much for the modern (super-)computers
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm having like an assesment exercise.
So given a Number, for example 12345, I must find out the sum sequence of the digits of the given number (1 + 2 +3 + 4 +5) and then add to it the result (15), and repeat this till the sum sequence of the last number is a digit (in this case is 6).
Example : 12345 + 15 + 6 = 12366;
666 + 24 + 6 = 696;
I've been thinkig to store the digits in an array, but then I realized the array's size is static. Now I'm thinking to make a linked list, but I'm not really sure. Does it involve linked lists?
Just guide me to the right path. What should I use?
There's no magic needed here. Just do the obvious computation on integers:
int reduce(int n)
{
int result = 0;
while (n != 0) { result += n % 10; n /= 10; }
return result;
}
int your_problem(int n)
{
int result = n;
while (n >= 10) { n = reduce(n); result += n; }
return result;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
This is the link of the problem.
https://projecteuler.net/problem=8
below is my code.
#include <stdio.h>
int main() {
long i,sum;
long temp = 0;
long arr[1000] = {
// Increasingly large number is ommitted//
// I just add ',' between each numbers//};
for(i=0; i<988; i++){
sum = arr[i]*arr[i+1]*arr[i+2]*arr[i+3]*arr[i+4]*arr[i+5]*arr[i+6]
*arr[i+7]*arr[i+8]*arr[i+9]*arr[i+10]*arr[i+11]*arr[i+12];
if(temp<sum){
temp = sum;
}
}
printf("%ld",temp);
return 0;
}
so I got 2091059712 which seems kind of reasonable answer.
The real problem here is, that you did not account for the size of the product. An integer is 10 digits max (2,147,483,647). So this or something alike might happen:
sum = 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9;
This gives: 2,541,865,828,329 which overflows your integer leading to undefined behaviour.
Use a larger integer type or take a different approach.
That's a brute force solution that will work fine for this size of problem.
Potential improvements:
Split the array on "0", and only test the substrings that are longer than the desired length.
Print out the numbers that ended up being the best substring. That way you can test that it actually is present in the original and the multiplication is done correctly.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I was experimenting with making my own random number generator and was surprised how easy it was to generate random numbers by doing something like this.
#include <iostream>
using namespace std;
int main(){
unsigned int number = 1;
for ( unsigned int i = 0; i < 0xFFFF ; i++ ){
unsigned int * data[0xFFFF];
number = number << 1;
number = number ^ (unsigned int)&data[i];
}
cout << number << endl;
while (1);
}
My question is, how effective is this, I mean, it seems to generate pretty random numbers, but how easy would it be to figure out what the next number is going to be?
The addresses of the data items are (in practice, because they'll be the same in each iteration) monotonically increasing. They're used as a one-time entropy source. Since they're monotonically increasing they're not a very good source of entropy.
In effect, for 32-bit code your code is equivalent to this:
auto main() -> int
{
unsigned number = 1;
unsigned const entropy = 123456; // Whatever.
for ( unsigned i = 0; i < 0xFFFF ; ++i )
{
number = number << 1;
number = number ^ (entropy + 4*i);
}
}
Regarding
” How easy would it be to figure out what the next number is going to be
as I see it that's not quite the right question for a pseudo-random number generator, but still, it's very easy.
Given two successive pseudo-random numbers A and B, computing (A << 1) ^ B yields X = entropy + 4*i. Now you can compute (B << 1) ^ (X + 4) and that's your next pseudo-random number C.
As I recall pseduo-random number generators are discussed in volume 1 of Donald Knuth's The Art of Computer Programming.
That discussion includes consideration of statistical measures of goodness.
It's not random at all. not even pseudo,
It has no state and all the input bits are discarded
basically you're pulling some junk off the stack and manipulating it a bit
in many contexts it will always give the same result.