I have written a program to store a number (which is predefined by the programmer) in form of digits in an array.
For example, if I want to store a number 1234 in array arrx[4], then its elements would be:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
I try to achieve this using the below piece of code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int arrx[4]; // Stores the individual digits of number as array
int digx = 4; // Total number of digits in number
int i;
long int dupx = 1234; // Number which has to be stored in array
for(i = digx-1; i >= 0 ; i--)
{
arrx[digx-i-1] = int(dupx/pow(10,i));
dupx = dupx%(pow(10, i));
}
return 0;
}
However, when I try to compile the above code, I get the following error message:
error: invalid operands of types 'long int' and 'double' to binary 'operator%'
The only conclusion which I was able to draw from above error was that the problem is with the modulus operator.
Therefore, I have following questions in my mind
What exactly is the problem with the code containing modulus operator?
How can I fix this?
I am using Code::Blocks version 17.12 with GNU GCC as my compiler.
You can only use % with integers, and pow produces floating-point numbers.
You could write an integer power function, or use a predefined table, but it's simpler to reverse the order of construction and start with the rightmost digit:
int main()
{
int arrx[4]; //stores the individual digits of number as array
int digx = 4; //total number of digits in number
long int dupx = 1234; //number which has to be stored in array
for(int i = 0; i < digx; i++)
{
arrx[digx-i-1] = dupx%10;
dupx = dupx/10;
}
return 0;
}
std::pow in its various guises returns a floating point type, even if the arguments are integral types.
Since % requires integral arguments, compilation will fail.
Using (long)(pow(10,i)) is one fix, checking of course that (long) is long enough. Note though that even under IEEE754 pow is not required to return the best floating point value possible, so the truncation to long can occasionally be harmful; perhaps std::round followed by the cast to long is to be preferred. Although the current fashion is to consider any implementation of pow that breaks for integral arguments to be defective.
In your case though I'd be tempted to define
constexpr/*use const on earlier standards*/ int powers[] = {1, 10, 100, 1000};
and index appropriately.
Related
I was solving a problem "Count the number of digits in a factorial", and stored the answer in two data types int and double. The answers from both the datatypes are different, and the one stored in double was finally correct. How is this happening?
Here's the code:
int n;
cin>>n;
double ans;
int ans_int;
double digits = 0;
int digit_int = 0;
for (int i = 1; i<=n; i++) {
digits += log10(i);
digit_int += log10(i);
}
ans = floor(digits)+1;
ans_int = floor(digit_int)+1; // This gives wrong answer.
cout<<ans<<endl;
If in the above code, I make digits as int, instead of double, I get an answer as 1 digit, in 5! instead of 3, similarly in other cases.
Converting a double number to int rounds it down to the nearest integer first. So if you add up say log10(x) for x ≤ 10 ≤ 99, the logarithm is always between 1 and 2, but converting to int will only add 1, instead of the correct value.
The problem lies in this line: digit_int += log10(i);. When i is less than 10, then its logarithm will be less than 1. Adding less than one to an integer will effectively add zero.
I've got a problem with returned value by std::pow(). Basically, I have following line in the code:
#include <cmath>
int main()
{
double rate = 1.0033333333333334;
int m = 360;
unsigned int period = 1;
double res = std::pow(rate, -(m-period+1));
}
And res has a value of inf. However, when I paste std::pow(rate, -(m-period+1)) to Visual Studio watch while debugging it has a proper value of 0.30179586515268314. Does anyone know what's the source of this discrepancy?
See http://coliru.stacked-crooked.com/a/ec78c5172cf53e03
Your problem comes from the -(m-period+1) part of your call to pow. period is declared as
unsigned int period = 1;
so when
-(m-period+1)
gets evaluated you have
-(int - unsigned int + int)
== -(unsigned int)
so you get 360 as an unsigned int and when you negate it, it wraps around and becomes a very large number (4294966936 for a 32 bit int). That means you are doing
1.0033333333333334 ^ 4294966936
not
1.0033333333333334 ^ -360
You need to make period an int to get the correct results.
If you have a number that must not be negative, don't use an unsigned type. Nothing about unsigned stops negative numbers, it just turns them into a positive number. If you want to make sure a number isn't negative, use a signed type and an if statement.
I'm trying to understand exactly what happens when indexing through an array with a float value.
This link: Float Values as an index in an Array in C++
Doesn't answer my question, as it states that the float should be rounded to an integer. However in the code I'm trying to evaluate, this answer does not make sense, as the index value would only ever be 0 or 1.
I'm trying to solve a coding challenge posted by Nintendo. To solve the problem there is an archaic statement that uses a bitwise assignment into an array using a long complicated bitwise expression.
The array is declared as a pointer
unsigned int* b = new unsigned int[size / 16]; // <- output tab
Then it's assigned 0's to each element
for (int i = 0; i < size / 16; i++) { // Write size / 16 zeros to b
b[i] = 0;
}
Here's the beginning of the statement.
b[(i + j) / 32] ^= // some crazy bitwise expression
The above sits inside of a nested for loop.
I'm sparing a lot of code here, because I want to solve as much of this problem on my own as possible. But I'm wondering if there is a situation were you would want to iterate through an array like this.
There must be more to it than the float just automatically casting to an int. There hast to be more going on here.
There are no floats here. size is an integer, and 16 is an integer, and consequently size/16 is an integer as well.
Integer division rounds towards zero, so if size is in [0,16), then size/16 == 0. If size is in [16,32), then size/16 == 1, and so on. And if size is in (-16, 0], then size / 16 == 0 as well.
([x,y) is the "half-open" interval from x to y: that is, it contains every number between x and y, and furthermore it includes x but excludes y)
The subscript operator in terms of arrays is syntactic sugar. When you have the following :
class A {...};
A ar[17];
std::cout << ar[3] << std::endl;
Saying ar[3] is no different than saying :
*(ar + 3);
So ar[3.4] is the same as saying
*(ar + 3.4) (1)
From the C++ Standard section 5.7.1 - Additive operators we read that :
(...) For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type.
that's why expression (1) causes compilation error.
So, when you index an array by a float you get a compilation error
To answer the question in the title:
#include <stdio.h>
int main(int argc, char** argv) {
int x[5];
int i;
for (i = 0; i < 5; ++i)
x[i] = i;
x[2.5] = 10;
for (i = 0; i < 5; ++i)
printf("%d\n", x[i]);
}
if i compile this with gcc i get a compiler error:
foo.c:10: error: array subscript is not an integer
I know from previous threads on this topic that using float arithmetic causes precision anomalies. But Interestingly I observed that the same function is behaving in two different ways.Using COUT output is 4 but if I am saving the result into a variable, then result is 3!
#include <iostream>
#include <cmath>
using namespace std;
#define mod 1000000007
long long int fastPower(long long int a, int n){
long long int res = 1;
while (n) {
if (n & 1) res = (res * a) % mod;
n >>= 1; a = (a * a) % mod;
}
return res;
}
int main() {
int j = 3;
cout << pow(64, (double)1.0/(double)j) << endl; // Outputs 4
int root = pow(64, (double)1.0/(double)j);
cout << root << endl; // Outputs 3
/* As said by "pts", i tried including this condition in my code but including this line in my code resulted in TimeLimitExceeded(TLE). */
if (fastPower(root+1,j) <= 64) root++;
cout << root << endl; // Outputs 4 :)
return 0;
}
Code output on Ideone.com
Now, how can we avoid such errors in a programing contest.
I do not want to use 'round' function because I need only integer value of root. i.e
63(1/6) = 1, 20(1/2) = 4, etc...
How should I modify my code so that correct result is stored in the root variable.
pow returns double. When cout is used, it is rounded(thus, it is 4). When you cast it to int, it just truncates fractional part. Pow returns something like 4 - eps(because of precision issues). When it is just truncated, it is equal to 3.
Dirty hack useful in programming contests: int root = (int)(pow(...) + 1e-7)
As far as I know, there is no single-line answer in C and C++ for getting the ath root of b rounded down.
As a quick workaround, you can do something like:
int root(int a, int b) {
return floor(pow(b, 1.0 / a) + 0.001);
}
This doesn't work for every value, but by adjusting the constant (0.001), you may get lucky and it would work for the test input.
As a workaround, use pow as you use it already, and if it returns r, then try r - 1, r and r + 1 by multiplying it back (using fast exponentiation of integers). This will work most of the time.
If you need a solution which works 100% of the time, then don't use floating point numbers. Use for example binary search with exponentiation. There are faster algorithms (such as Newton iteration), but if you use them on integers then you need to write custom logic to find the exact solution as soon as they stop converging.
There are two problems with your program:
The pow(int, int) overload is no longer available. To avoid this problem, cast the first parameter to double, float, or long double.
Also, command of cout is rounding off your answer in upper roof (3.something into 4) and saving your data is removing all the decimal part and is accepting only integer part.
Trying to understand radix sort for my data structures class. My teacher showed us a sample of radix sort in C++. I don't understand what the for loop for the digits does, she said something about maximum digits. Also when I try this in VS it says log10 is an ambiguous call to an overloaded function.
void RadixSort(int A[], int size)
{
int d = 1;
for(int i = 0; i < size; ++i)
{
int digits_temp;
digits_temp=(int)log10(abs(A[i]!=0 ? abs(A[i]) : 1)) +1;
if(digits_temp > d)
d = digits_temp;
}
d += 1;
*rest of the implementation*
}
Can anyone explain what this for loop does and why i get that ambiguous call error? Thanks
That piece of code is just a search for the number of digits needed for the "longest" integer; that's probably needed to allocate some buffer later.
log10 gives you the power of ten that corresponds to its argument, which, rounded to the next integer (hence the +1 followed by the (int) cast, which results in truncation), gives you the number of digits required for the number.
The argument of log10 is a bit of a mess, since abs is called twice when just once would suffice. Still, the idea is to pass to log10 the absolute value of the number being examined if it's not zero, or 1 if it is zero - this because, if the argument were zero, the logarithm would diverge to minus infinity (which is not desirable in this case, I think that the conversion to int would lead to strange results).
The rest of the loop is just the search for the maximum: at each iteration it calculates the digits needed for the current int being examined, checks if it's bigger than the "current maximum" (d) and, if it is, it replaces the "current maximum".
The d+=1 may be for cautionary purposes (?) or for the null-terminator of the string being allocated, it depends on how d is used afterward.
As for the "ambiguous call" error: you get it because you are calling log10 with an int argument, which can be converted equally to float, double and long double (all types for which log10 is overloaded), so the overload to choose is not clear to the compiler. Just stick a (double) cast before the whole log10 argument.
By the way, that code could have been simplified/optimized by just looking for the maximum int (in absolute value) and then taking the base-10 logarithm to discover the number of digits needed.
Log base 10 + 1 gives you the total number of digits present in a number.
Essentially here, you are checking every element in the array A[] and if the element is == 0 you store 1 in the digits_temp variable.
You initialize d = 1 as a number should have atleast 1 digit, and if it has more than 1 you replace it with the number of digits calculated.
Hope that helps.
There are 3 types of definition for log10 function which are float,double,long double input.
log10( static_cast<double> (abs(A[i]!=0 ? abs(A[i]) : 1)) );
So you need to static cast it as double to avoid the error.
(int)log10(x)+1 gives the number of digit present in that number.
Rest is simple implementation of Radix Sort
You see the warning because log10 is defined for float, double and long double but not integer and it's being called with a integer. The compiler can convert the int into any of those types so the call is ambiguous.
The for loop is doing a linear search for the maximum of digits in any of the numbers in the array. It is unnecessarily complicated and slow because you can simply searched for the largest absolute value in A then taken the log10 of that.
void RadixSort(int A[], int size)
{
int max_abs = 1;
for(int i = 0; i < size; ++i)
{
if(abs(A[i] > max_abs)
max_abs = abs(A[i]);
}
int d += log10(float(max_abs));
/* rest of the implementation */
}
Rest of code is missing so cant exactly determined usage.
But basically Radix sort goes over all INTEGERS and sort them comparing Digit Digit starting from least significant upwards.
the first part of code only determines the max digit count+1 from integers in array, this could be used to normalize all numbers to same length for easy handling.
i.e (1,239,2134) to (0001,0239,2134)