This fuction convert Decimal number to Binary (I've founded it on Internet)
foo(long dec)
{
long int rem,i=1,sum=0;
do
{
rem=dec%2;
sum=sum + (i*rem);
dec=dec/2;
i=i*10;
} while(dec>0);
return sum;
}
As I found out, when I change type "long" to "int", the function doesn't work for number bigger than 1023. The problem is I have to run this function with integer argument (It has to be foo(int dec)). I have tried to use static_cast but I've failed.
error: cannot convert ‘long int’ to ‘std::ios_base&(std::ios_base&)’ in assignment|
Is there any way to bypass that or maybe change this function somehow.
Thank you for you help.
First of all, this function doesn't exactly "convert decimal to binary". Instead, it will convert a number such that if you print out the result in base 10, then it looks like the binary representation of the number.
Secondly this function definition is invalid because you did not specify a return type.
Of course, if you change long to int in the parameter list, and add int as return type (and your system has smaller ints than longs - some don't) then it will not work for as may numbers.
For example, if your system has 32-bit ints then 1111111111 is the largest output that will work, and that comes from input 1023.
I don't know what you're talking about with the static_cast and ios_base error, you must have done something unrelated to this function.
Make sure you define the type that the function is returning in the function definition, and make sure foo is taking a long int as an argument.
long int foo(long int) {
code...
}
Related
We know that -2*4^31 + 1 = -9.223.372.036.854.775.807, the lowest value you can store in long long, as being said here: What range of values can integer types store in C++.
So I have this operation:
#include <iostream>
unsigned long long pow(unsigned a, unsigned b) {
unsigned long long p = 1;
for (unsigned i = 0; i < b; i++)
p *= a;
return p;
}
int main()
{
long long nr = -pow(4, 31) + 5 -pow(4,31);
std::cout << nr << std::endl;
}
Why does it show -9.223.372.036.854.775.808 instead of -9.223.372.036.854.775.803? I'm using Visual Studio 2015.
This is a really nasty little problem which has three(!) causes.
Firstly there is a problem that floating point arithmetic is approximate. If the compiler picks a pow function returning float or double, then 4**31 is so large that 5 is less than 1ULP (unit of least precision), so adding it will do nothing (in other words, 4.0**31+5 == 4.0**31). Multiplying by -2 can be done without loss, and the result can be stored in a long long without loss as the wrong answer: -9.223.372.036.854.775.808.
Secondly, a standard header may include other standard headers, but is not required to. Evidently, Visual Studio's version of <iostream> includes <math.h> (which declares pow in the global namespace), but Code::Blocks' version doesn't.
Thirdly, the OP's pow function is not selected because he passes arguments 4, and 31, which are both of type int, and the declared function has arguments of type unsigned. Since C++11, there are lots of overloads (or a function template) of std::pow. These all return float or double (unless one of the arguments is of type long double - which doesn't apply here).
Thus an overload of std::pow will be a better match ... with a double return values, and we get floating point rounding.
Moral of the story: Don't write functions with the same name as standard library functions, unless you really know what you are doing!
Visual Studio has defined pow(double, int), which only requires a conversion of one argument, whereas your pow(unsigned, unsigned) requires conversion of both arguments unless you use pow(4U, 31U). Overloading resolution in C++ is based on the inputs - not the result type.
The lowest long long value can be obtained through numeric_limits. For long long it is:
auto lowest_ll = std::numeric_limits<long long>::lowest();
which results in:
-9223372036854775808
The pow() function that gets called is not yours hence the observed results. Change the name of the function.
The only possible explaination for the -9.223.372.036.854.775.808 result is the use of the pow function from the standard library returning a double value. In that case, the 5 will be below the precision of the double computation, and the result will be exactly -263 and converted to a long long will give 0x8000000000000000 or -9.223.372.036.854.775.808.
If you use you function returning an unsigned long long, you get a warning saying that you apply unary minus to an unsigned type and still get an ULL. So the whole operation should be executed as unsigned long long and should give without overflow 0x8000000000000005 as unsigned value. When you cast it to a signed value, the result is undefined, but all compilers I know simply use the signed integer with same representation which is -9.223.372.036.854.775.803.
But it would be simple to make the computation as signed long long without any warning by just using:
long long nr = -1 * pow(4, 31) + 5 - pow(4,31);
As a addition, you have neither undefined cast nor overflow here so the result is perfectly defined per standard provided unsigned long long is at least 64 bits.
Your first call to pow is using the C standard library's function, which operates on floating points. Try giving your pow function a unique name:
unsigned long long my_pow(unsigned a, unsigned b) {
unsigned long long p = 1;
for (unsigned i = 0; i < b; i++)
p *= a;
return p;
}
int main()
{
long long nr = -my_pow(4, 31) + 5 - my_pow(4, 31);
std::cout << nr << std::endl;
}
This code reports an error: "unary minus operator applied to unsigned type, result still unsigned". So, essentially, your original code called a floating point function, negated the value, applied some integer arithmetic to it, for which it did not have enough precision to give the answer you were looking for (at 19 digits of presicion!). To get the answer you're looking for, change the signature to:
long long my_pow(unsigned a, unsigned b);
This worked for me in MSVC++ 2013. As stated in other answers, you're getting the floating-point pow because your function expects unsigned, and receives signed integer constants. Adding U to your integers invokes your version of pow.
I am writing a function in which I have to calculate factorial of numbers and do operations on them.The return value of the function should be long long so I think it would be better to do all operations in long long format. If I am wrong please correct me.
The tgamma() function by itself returns the correct value in scientific notation. But the the value returned by tgamma() is sometimes 1 less than actual answer when the value returned by the function is typecasted to 'long long'.
int main()
{
std::cout<<"11!:"<<tgamma(12)<<std::endl;
std::cout<<"12!"<<tgamma(13)<<std::endl;
std::cout<<"13!"<<tgamma(14)<<std::endl;
std::cout<<"14!"<<tgamma(15)<<std::endl;
std::cout<<"15!"<<tgamma(16)<<std::endl;
std::cout<<"16!"<<tgamma(17)<<std::endl;
std::cout<<"********************************"<<std::endl;
std::cout<<"11!:"<<(long long)tgamma(12)<<std::endl;
std::cout<<"12!"<<(long long)tgamma(13)<<std::endl;
std::cout<<"13!"<<(long long)tgamma(14)<<std::endl;
std::cout<<"14!"<<(long long)tgamma(15)<<std::endl;
std::cout<<"15!"<<(long long)tgamma(16)<<std::endl;
std::cout<<"16!"<<(long long)tgamma(17)<<std::endl;
return 0;
}
I am getting the following output:
11!:3.99168e+07
12!4.79002e+08
13!6.22702e+09
14!8.71783e+10
15!1.30767e+12
16!2.09228e+13
********************************
11!:39916800
12!479001599
13!6227020799
14!87178291199
15!1307674367999
16!20922789888000
The actual value of 15! according to this site is 1307674368000 but when I typecast tgamma(16) to long long, I get only 1307674367999. The thing is this discrepancy only appears for some numbers. The typecasted answer for 16! is correct - 20922789888000.
This function is for a competitive programming problem which is currently going on, so I can't paste the function and the solution I am developing to it here.
I would roll my own factorial function but I want to reduce the number of characters in my program to get bonus points.
Any tips on how to detect this discrepancy in typecasted value and correct it? Or maybe some other function that I can use?
Obviously, unless we have very unusual implementation, not all long long numbers can be exactly represented as double. Therefore, tgamma cannot store double values such that casting to long long would produce exact value. Simply there are more long long values than double values within long long interval.
If you want exact long long factorial, you should implement it yourself.
On top of this, if you want precision, you transform double to long long not as (long long)x, but as (long long)round(x), or (long long)(x+0.5), assuming x is positive.
Casting from a floating point type to an integral type truncates. Try (long long) roundl(tgammal(xxx)) to get rid of integer truncation error. This is also using long doubles so it may give you more digits.
#include <math.h>
#include <iostream>
int main(){
std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl;
std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl;
std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl;
std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl;
std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl;
std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl;
std::cout<<"********************************"<<std::endl;
std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl;
std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl;
std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl;
std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl;
std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl;
std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl;
return 0;
}
Gives:
11!:39916800
12!479001600
13!6227020800
14!87178291200
15!1307674368000
16!20922789888000
********************************
11!:39916800
12!479001600
13!6227020800
14!87178291200
15!1307674368000
16!20922789888000
Why should I get this error
C2668: 'abs' : ambiguous call to overloaded function
For a simple code like this
#include <iostream>
#include <cmath>
int main()
{
unsigned long long int a = 10000000000000;
unsigned long long int b = 20000000000000;
std::cout << std::abs(a-b) << "\n"; // ERROR
return 0;
}
The error still presents after removing std::. However if I use int data type (with smaller values) there is no problem.
The traditional solution is to check that manually
std::cout << (a<b) ? (b-a) : (a-b) << "\n";
Is that the only solution?
The check seem the only really good solution. Alternatives require type bigger than yours and nonstandard extension to use it.
You can go with solutions casting to signed long long if your range fits. I would hardly suggest that way, especially if the implementation is placed in a function that does only that.
You are including <cmath> and thus using the "floating-point abs".
The "integer abs" is declared in <cstdlib>.
However, there is no overload for unsigned long long int (both a and b are, thus a-b is, too), and the overload for long long int only exists since C++11.
First, you need to include the correct header. As pointed out by gx_, <cmath> has a floating-point abs and on my compiler it actually compiles, but the result is probably not the one you expected:
1.84467e+19
Include <cstdlib> instead. Now the error is:
main.cpp:7:30: error: call of overloaded ‘abs(long long unsigned int)’ is ambiguous
main.cpp:7:30: note: candidates are:
/usr/include/stdlib.h:771:12: note: int abs(int)
/usr/include/c++/4.6/cstdlib:139:3: note: long int std::abs(long int)
/usr/include/c++/4.6/cstdlib:173:3: note: long long int __gnu_cxx::abs(long long int)
As you can see, there is no unsigned overload of this function, because computing an absolute value of something which is of type unsigned makes no sense.
I see answers suggesting you to cast an unsigned type to a signed one, but I believe this is dagereous, unless you really know what you are doing!
Let me ask first what is the expected range of the values a and b that you are going to operate on? If both are below 2^63-1 I would strongly suggest to just use long long int. If that is not true however, let me note that your program for the values:
a=0, b=1
and
a=2^64-1, b=0
will produce exactly the same result, because you actually need 65 bits to represent any possible outcome of a difference of 2 64-bit values. If you can confirm that this is not going to be a problem, use the cast as suggested. However, if you don't know, you may need to rethink what you are actually trying to achieve.
Because back before C++ with C you used to have use abs, fabs, labs for each different type, c++ allows overloading of abs, in this case it doesn't understand or isn't happy with your overload.
Use labs(a-b) seeing as you're using longs, this should solve your problem.
I have a strange problem. I have created a simple function to convert from decimal to binary. The argument is a int value that represents the number in decimal, and the function returns a bitset that represent the binary number.
The problem is that conversion for a binary number smaller than 10000000000000000000000000000000 (2,147,483,648 in decimal) works perfectly, but when the number to be converted is higher, the conversion doesn't work properly. Where is the mistake???
Here I send you the function:
bitset<15000> Utilities::getDecToBin(int dec)
{
bitset<15000> columnID;
int x;
for(x=0;x<columnID.size();x++)
{
columnID[x]=dec%2;
dec=dec/2;
}
return columnID;
}
Thanks in advance for all your help! :D
The range for an 32 bit int is −2,147,483,648 to 2,147,483,647.
If by larger you mean 1073741825, then I can't see anything wrong.
If you mean adding an extra bit at the most significant position (i.e. 2147483648) then you might be running into signed/unsigned issues.
I see that you restrict your loop by the size of columnID. It would be a good idea to limit it by the size of dec in bits too, or stop when dec is 0.
You should use a long int, an array of long int or even a string as input to your method (depending on the source of your data and how you will call your function).
I am surprised it only works up to 30 bits, you should be able to manage 31 but for 32 bits you would need unsigned ints. If you used unsigned 64-bit integers you could manage a lot more than that, but 15,000-bit integers are something that can only be implemented through special classes.
struct DummyStruct{
unsigned long long std;
int type;
};
DummyStruct d;
d.std = 100;
d.type = 10;
/// buggy printf, unsigned long long to int conversion is buggy.
printf("%d,%d\n",d.std, d.type); // OUTPUT: 0,100
printf("%d,%d\n", d.type, d.std); // OUTPUT: 10,100
printf("%lld,%d\n",d.std, d.type); // OUTPUT: 100,10
Please tell me why unsigned long long to int conversion is not properly handled in printf. I am using glibc.
Is this bug in printf ?
why printf does not do internal type conversion ?
The %d argument tells printf to interpret the corresponding argument as an int. Try using %llu for long long. And memorize this reference card.
(So no, it's not a bug)
Its your usage that is the problem.
Unless the types specified in the format string are exactly the same as the types in the parameters then things will not work correctly.
This is because the compiler pushes the parameters as-is onto the stack.
There is not type checking or conversion.
At run-time the code is pulling the values of the stack and advancing to the next object based on the value in the format string. If the format string is wrong then the amount advanced is incorrect and you will get funny results.
Rule one: The chances of you finding a bug in the library or the compiler are very, very slim. Always assume the compiler / library is right.
Parameters are passed to printf() through the mechanisms in <stdarg.h> (variable argument lists), which involves some magic on the stack.
Without going into too much detail, what printf() does is assuming that the next parameter it has to pull from the stack is of the type specified in your format string - in the case of %d, a signed int.
This works if the actual value you've put in there is smaller or equal in width to int, because internally any smaller value passed on the stack is extended to the width of int through a mechanism called "integer promotion".
This fails, however, if the type you have passed to printf() is larger than int: printf() is told (by your %d) to expect an int, and pulls the appropriate number of bytes (let's assume 4 bytes for a 32 bit int) from the stack.
In case of your long long, which we'll assume is 8 bytes for a 64 bit value, this results in printf() getting only half of your long long. The rest is still on the stack, and will give pretty strange results if you add another %d to your format string.
;-)
With printf (which is one of the very old functions from original C) the compiler does not cast the paramters after the format list to the desired type, i.e. you need to make sure yourself that the types in the parameter list match the one in the format.
With most other functions, the compiler squeezes the given parameter into the declared types, but printf, scanf and friends require you to tell the compiler exactly which types are following.