I am trying to convert a string to number(long double) in C++. The problem arises when the number of digits after decimal point is greater than 3. It automatically rounds-off the to the nearest third digit after the decimal.
Additional info:
compiler: mingw
os: win10
Here's the code (test.cpp):
#include<iostream>
#include <string>
#include <math.h>
using namespace std;
double long c2n(string n) {
double long num=0;
bool isdec = false, is_ve=false;
// is_ve checks if number is negative
// isdec checks if the decimal point is reached and numbers can be added after decimal
char c;
// to store the the character which needs to be checked
short i = 0, count=1;
if (n.at(0)=='-')
{
i=1;
is_ve=true;
}
for (; i < n.length(); ++i)
{
c=n.at(i);
if (c=='.'){
isdec=true;
continue;
}
if (!isdec)
num=num*10+(c-'0');
else{
num = num + (c-'0')/pow(10,count);
count++;
}
}
if (is_ve)
{
return -num;
}
return num;
}
int main(int argc, char const *argv[])
{
cout << c2n("-912.301956") << endl;
return 0;
}
Here's the output:
D:\--path-->g++ -o test.exe test.cpp
D:\--path-->test.exe
-912.302
What I discovered later:
if in the main function, we pass "-912.3016"
cout<< c2n("-912.3016") <<endl;
then output comes out to be:
D:\--path-->g++ -o test.exe test.cpp
D:\--path-->test.exe
-912.302
but if we pass "-912.3015"
cout << c2n("-912.3015") <<endl;
then the o/p:
D:\--path-->g++ -o test.exe test.cpp
D:\--path-->test.exe
-912.301
Should I take double instead of long double or there is any other problem?
The default precision of std::cout is 6 as set by std::ios_base::init. So
auto val = 1234.56789;
std::cout<<val<<'\n`;
yields 1234.57 i.e. 6 digits (and rounds it accordingly). Set the precision accordingly using setprecision from the iomanip header and you should be able to see the correct value.
std::cout << std::setprecision(12) << c2n("-912.301956") << std::endl;
Related
I want to count the number of recursivily call that has a number in the Collatz Sequence. But for such a bigger number for example 4565458458
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int f(int value){
if(value==1) return 1;
else if(value%2 == 0) return value/2;
else return 3*value+1;
}
int g(int value){
if(value == 0) return 0;
if (f(value)==1) return 1;
return 1 + g(f(value));
}
int main(int argc, char *argv[]){
int nSteps=0;
istringstream iss(argv[1]);
int;
if(!(iss >> num).fail()){
if(num < 0) cout << "0" << endl;
else{
nSteps = g(num);
cout << "Result: " << nSteps << endl;
}
}
else{
cout << "Incorrect line paramaters: ./g n" << endl;
}
return 0;
}
Your program will use a lot of stack-memory for large inputs.
In addition f should have the same input and output type (originally it had "unsigned long long" as input and int as output), or the result will be wrong.
I would advise you to first rewrite g without recursion, and if that works try to investigate how to get g to be efficient with tail-recursion (the current variant does probably not support it).
Using a debugger as others suggested is also good, especially if it crashes before calling 'g'.
Finally 'num<0' does not make sense for an unsigned 'num'.
I wrote a code to get the factorial of a number in C++.
Here is the code.
#include <iostream>
using namespace std;
unsigned long long getFactorial(int);
int main(int argc, char **argv) {
int num = 5;
unsigned long long factorial = getFactorial(a);
cout << "Factorial of " << num << ": " << factorial << endl;
return 0;
}
unsigned long long getFactorial(int num) {
int i;
unsigned long long factorial = 1;
for(i=1; i<=num; i++) {
factorial *= i;
}
return factorial;
}
When I assign 5 to the num value, it properly prints out the right value, 120. But when I assign bigger numbers, for example 100, it simply prints out 0. How can I modify the code to properly print out the result on the console?
Now I found the answer by myself.
By using the gmp library, it became much easier to deal with the big integers.
Here's the modified code.
#include <iostream>
#include <gmpxx.h>
using namespace std;
mpz_class getFactorial(int);
int main(int argc, char **argv) {
int num = 100;
mpz_class factorial = getFactorial(num);
cout << "Factorial of " << num << ": " << factorial << endl;
return 0;
}
mpz_class getFactorial(int num) {
int i;
mpz_class factorial = 1;
for(i=1; i<=num; i++) {
factorial *= i;
}
return factorial;
}
In order to use the gmp library, I included the <gmpxx.h> header file. Next I changed the data type of the factorial variable and the return type of the getFactorial() function from unsigned long long to mpz_class which is the data type that represents the big integer.
After modifying the code, I compiled with GCC using the following flags.
$gcc test.cpp -lstdc++ -lgmpxx -lgmp -o test
The -lgmpxx and -lgmp flags are required to compile the code using the gmp library.
Now it works fine.
How to print a number with precision given by the user. And how to print precision after decimal point up to 100 digits.
Suppose A,B,C be three numbers and take the value of three numbers from the user and I have to print the answer of A/B ( A divided by B ) to C floating points.
If A=22, B=7 , C=25, that means I have to print the result of 22/7 to 25 floating points.
3.1428571428571428571428571 , this is the answer of 22/7 , 25 digits after decimal point.
As many have pointed out, use std::fixed and std::setprecision
#include <iostream>
#include <iomanip>
int main()
{
float x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
But when you run this you will see the output is
3.1428570747375488281250000 when it should be
3.1428571428571428571428571. What gives?
Well, floats can only hold so much before having to give up and say, "Best I can do, mate." Rumour has it, this point is about 7 digits. Based on a quick count that looks about right.
So what say we try a double. They're twice the size!
#include <iostream>
#include <iomanip>
int main()
{
double x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
gives us
3.1428571428571427937015414. Still not
3.1428571428571428571428571, but closer. What have we got that's bigger than double? Just tried long double. No dice on my computer. Looks like we're going to have to go looking for a good high precision floating point library.
Bummer. Well, there is one in Boost. I someday expect to see boost::kitchen_sink.
To print a float with a precision "n" you should write :
printf("%.nf"); // like printf("%.3f")
there you are a c++ full code
#include <stdio.h>
#include <stdlib.h>
#include <strstream>
#include <iostream>
int main()
{
// print a float with precision '4'
printf("%.4f",10.125f);
// print a float with precision 'n'
char * buffer = new char[100];
int n;
std::strstream ss; // like cout but outputs to a string buffer
ss<<"%.";
std::cout<<"Enter precision : ";
std::cin>>n;
ss<<n<<"f";
printf(ss.str(),10,125); // ss.str() to get buffer content
delete[] buffer;
return 0;
}
but very simply you still can write
std::cout << std::setprecision(n) << float_var;
EDIT :
you can do you own division ! i mean you can simulate the devision of the processor and get whatever precision you want , till inifinity ! , there you are the amazing code that i wrote for my friend one time for fun :
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <chrono>
int main()
{
std::cout.sync_with_stdio(false); // accelerate output
register int x,y;
char opp;
std::cout<<"Enter x/y : ";
std::cin>>x>>opp>>y;
std::cout<<"deviding "<<x<<" by "<<y<<std::endl;
register int precision;
std::cout<<"Enter precision : ";
std::cin>>precision;
register int precision_counter = 0;
typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::nanoseconds ms;
typedef std::chrono::duration<float> fsec;
auto t0 = Time::now();
std::cout <<"Result = ";
std::cout<<x/y;
// check if there will be a float point result to print a point
if(x<y || x%y != 0)
{
std::cout<<".";
x%=y; // remove what we printed
register int counter = 0;
// print digts that are after the float point
while (precision_counter<precision )
{
x*=10;
while (x>=y)
{
x-= y;
counter++;
}
std::cout<<counter;
counter = 0;
precision_counter++;
}
/*
optimized loop :
while (precision_counter<precision )
{
x*=10;
std::cout<<x/y;
x%=y;
precision_counter++;
}
**/
}
auto t1 = Time::now();
fsec fs = t1 - t0;
std::cout<<"\n";
ms d = std::chrono::duration_cast<ms>(fs);
std::cout << fs.count() << "s\n";
std::cout << d.count() << " nanosecond\n";
std::cout<<std::endl;
system("pause");
return 0;
}
#include <iostream>
#include <string>
#include <sstream>
std::string f(int A, int B, int C){//A: numerator, B:denominator, C:digits after decimal point
std::stringstream ss;
int count = 0;
if(A < 0){
A = -A;
++count;
}
if(B < 0){
B = -B;
++count;
}
if(count == 1)
ss << '-';
ss << A / B << '.';
A %= B;
A *= 10;
count = C;
while(count--){
ss << A / B;
A %= B;
A *= 10;
}
return ss.str();
}
int main(void){
std::cout << f(22, 7, 25) << std::endl;
return 0;
}
I have written a class that returns a random string after you provide a seed, a sequence length, and a character set as shown below.
I would like to know how to catch any bad input, such as setting the seed to 0 or to a negative number.
The examples that I have seen have just used cout to send an error message and then exit(1); I am thinking about putting a bool flag as a private variable and setting it to false when invalid input is detected. Then after you attempt to generate a random string with this class you would just check that flag through an accessor function.
Is there a better and/or standard way of handling this that will not just exit the program like exit(1)? Any general input about the class is welcomed also. Thanks for the assistance.
RandomString.h
// This is the header file randomstring.h. This is the interface for the class RandomString.
// Values of this type are a random string of the specified length from the specified string character set.
// The values that are needed for input are a positive integer seed, an integer desired length, and a string character set.
// Uses the mt19937 random number engine with a uniform_int_distribution.
#ifndef RANDOMSTRING_H
#define RANDOMSTRING_H
#include <string>
#include <random>
using namespace std;
namespace RandomString
{
class RandomString
{
public:
RandomString(double newSeed, unsigned int newLength, string newCharacterSet); // Initializes the RandomString object with the provided arguments.
RandomString(); // Initializes the seed to 1, the length to 0, and the character set to '0'.
double getSeed();
unsigned int getLength();
string getCharacterSet();
string getSequence();
void setSeed(double newSeed); // Sets the new seed but does not produce a new random sequence.
void setLength(unsigned int newLength); // This is the length of randomSequence.
void setCharacterSet(string newCharacterSet);
void generateNext(); // Generates the next random sequence.
private:
double seed;
unsigned int length;
string characterSet;
string randomSequence;
mt19937 engine;
};
} // RandomString namespace
#endif
RandomString.cpp
// This is the implementation file randomstring.cpp. This is the implementation for the class RandomString.
// The interface for the class RandomString is in the header file randomstring.h.
#include "stdafx.h"
#include <string>
#include <random>
#include "randomstring.h"
using std::string;
using std::uniform_int_distribution;
namespace RandomString
{
RandomString::RandomString(double newSeed, unsigned int newLength, string newCharacterSet)
{
setSeed(newSeed);
setLength(newLength);
setCharacterSet(newCharacterSet);
}
RandomString::RandomString()
{
seed = 1;
length = 0;
characterSet = '0';
}
double RandomString::getSeed()
{
return seed;
}
unsigned int RandomString::getLength()
{
return length;
}
string RandomString::getCharacterSet()
{
return characterSet;
}
string RandomString::getSequence()
{
return randomSequence;
}
void RandomString::setSeed(double newSeed)
{
seed = newSeed;
engine.seed(seed);
}
void RandomString::setLength(unsigned int newLength)
{
length = newLength;
}
void RandomString::setCharacterSet(string newCharacterSet)
{
characterSet = newCharacterSet;
}
void RandomString::generateNext()
{
randomSequence.resize(length);
uniform_int_distribution<> distribution(0,characterSet.length() - 1);
for (int i = 0; i < length; i++)
{
randomSequence[i] = characterSet[distribution(engine)];
}
}
} // RandomString namespace
Finally, here is the test program that I am using.
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "randomstring.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
do
{
double seed = 0;
unsigned int length = 0;
cout << "Enter seed: ";
cin >> seed;
cout << "Enter length of string: ";
cin >> length;
cout << endl;
RandomString::RandomString randomTest(seed,length,"ABCDEFGHJKLMNPQRSTUVWXYZ1234567890");
cout << "class RandomString" << endl;
cout << "seed: " << randomTest.getSeed() << endl;
cout << "length: " << randomTest.getLength() << endl;
randomTest.generateNext();
cout << "random sequence: " << randomTest.getSequence() << endl;
randomTest.generateNext();
cout << "next random sequence: " << randomTest.getSequence() << endl << endl;
}while(true);
}
Throw an exception
void RandomString::setSeed(double newSeed)
{
if (newSeed <= 0) {
throw std::runtime_error("seed should be positive");
}
seed = newSeed;
engine.seed(seed);
}
User would have to use try catch to handle error, else std::terminate is called.
How about letting the user have another chance at giving a good input?
What is the next thing the user will do after they find out they have put in a bad input? There is a high chance they will try again with a good input so just ask for another one.
while(true)
{
cout << "Enter seed: ";
cin >> seed;
if(seed > 0)
{
cout << "ERROR: Seed must be greater than 0." << endl;
break;
}
}
To answer your question about the bool error flag, I wouldn't do it that way. I have no need for bad data that was generated from a bad seed. No data is better than bad data. I generally try to "fail early, fail often", meaning I should stop and report the error as soon as I realize it exists.
If you were set on storing it the error flag, I'd have generateNext() or setSeed return false rather than nothing if there was a problem. Exceptions also work, but are slower and some projects don't like them in C++.
If you plan to have others use RandomString, I'd change the method signature from a double to uint (unsigned int). This would catch negative numbers being used at compile time rather than run time...again helping to fail even earlier. Sounds like this might not work in your classroom scenario, but is a good principle in the real world.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Float to binary in C++
I want to print out the binary representation of a float number in C++. Not very practical, just out of curiosity.
The following program doesn't compile though. The reinterpret_cast fails. What kind of cast can I use so that I can do the " &(1 << i) " part?
#include <iostream>
using namespace std;
void toBinary(float num) {
int numi = reinterpret_cast<int>(num);
cout << num << " " << numi << endl;
for (int i = 0; i < 8 * sizeof(num); i++){
if (numi & (1<<i)) {
cout << 1;
} else {
cout << 0;
}
}
cout << endl << endl;
}
int main() {
float a;
cout << sizeof(int) << " " << sizeof(float) << endl;
a = 13.5;
toBinary(a);
toBinary(13.9);
toBinary(2 * a);
toBinary(-a);
}
There's a much easier way. Take a pointer to the float, and reinterpret_cast it to a pointer to char. Now loop through sizeof(float) and convert each char to 8 binary digits. This method works for doubles too.
Use a union. I did this code to do exactly what you want:
// file floattobinary.cc
#include <string>
#include <inttypes.h> // for uint32_t
using namespace std;
void floatToBinary(float f, string& str)
{
union { float f; uint32_t i; } u;
u.f = f;
str.clear();
for (int i = 0; i < 32; i++)
{
if (u.i % 2) str.push_back('1');
else str.push_back('0');
u.i >>= 1;
}
// Reverse the string since now it's backwards
string temp(str.rbegin(), str.rend());
str = temp;
}
Below is a test program to run this function:
// file test.cc
#include <iostream>
#include <string>
#include <cstdlib> // for atof(3)
using namespace std;
void floatToBinary(float, string&);
int main(int argc, const char* argv[])
{
string str;
float f;
if (argc > 1)
{
f = static_cast<float>(atof(argv[1]));
floatToBinary(f, str);
}
cout << str << endl;
return 0;
}
Compile and run (I'm using GNU g++ on Linux):
me#mypc:~/college/c++/utils$ g++ -c floattobinary.cc
me#mypc:~/college/c++/utils$ g++ -c test.cc
me#mypc:~/college/c++/utils$ g++ -o test *.o
me#mypc:~/college/c++/utils$ ls
floattobinary.cc floattobinary.o test* test.cc test.o
me#mypc:~/college/c++/utils$ ./test 37.73
01000010000101101110101110000101
me#mypc:~/college/c++/utils$ ./test 2.0
01000000000000000000000000000000
me#mypc:~/college/c++/utils$ ./test 0.0
00000000000000000000000000000000
me#mypc:~/college/c++/utils$ ./test 237.74
01000011011011011011110101110001
me#mypc:~/college/c++/utils$ ./test 2.74e12
01010100000111110111110100101111
me#mypc:~/college/c++/utils$ ./test 2.74e13
01010101110001110101110001111010
me#mypc:~/college/c++/utils$ ./test -88.37
11000010101100001011110101110001