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
Related
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;
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.
I'm using mpz_t for big numbers. I need to convert the mpz_t to binary representation. I tried to use the mpz_export, but the returned array contains only 0s.
mpz_t test;
mpz_init(test);
string myString = "173065661579367924163593258659639227443747684437943794002725938880375168921999825584315046";
mpz_set_str(test,myString.c_str(),10);
int size = mpz_sizeinbase(test,2);
cout << "size is : "<< size<<endl;
byte *rop = new byte[size];
mpz_export(rop,NULL,1,sizeof(rop),1,0,test);
Using gmpxx (since it's taged as c++)
#include <iostream>
#include <gmpxx.h>
int main()
{
mpz_class a("123456789");
std::cout << a.get_str(2) << std::endl; //base 2 representation
}
There should be equivalent function in plain GMP
You have a minor error in your code: sizeof(rop) is either 4 or 8, depending on whether a pointer is 4 or 8 bytes on your system. You meant to pass simply size, not sizeof(rop).
Here's some code that works for me, with g++ -lgmp -lgmpxx:
#include <stdio.h>
#include <iostream>
#include <gmpxx.h>
int main()
{
mpz_class a("173065661579367924163593258659639227443747684437943794002725938880375168921999825584315046");
int size = mpz_sizeinbase(a.get_mpz_t(), 256);
std::cout << "size is : " << size << std::endl;
unsigned char *rop = new unsigned char[size];
mpz_export(rop, NULL, 1, 1, 1, 0, a.get_mpz_t());
for (size_t i = 0; i < size; ++i) {
printf("%02x", rop[i]);
}
std::cout << std::endl;
}
I have written the following code to save in an char * array and print the following content:
band1.txt
band2.txt
...
band3.txt
The code seems right but what is printed on the console is very weird.
Code:
const char ** current_band = new const char * [103];
stringstream sstm;
string str;
for (i=0;i<103;i++){
current_band[i] = new char[11];
}
for (i=0;i<103;i++){
sstm.str("");
sstm << "band" << i+1 << ".txt";
str = sstm.str();
current_band[i] = str.c_str();
cout << current_band[i] << endl;
cout << i << endl;
}
for (i=0;i<103;i++){
cout << current_band[i] << endl;
cout << i << endl;
}
Console:
band1.txt
0
band2.txt
1
...
band103.txt
102
And then for the last loop:
band103.txt
0
band102.txt
1
band103.txt
2
band102.txt
3
...
band102.txt
101
band103.txt
102
How is this even possible?
EDIT: Actually i want the "bands" to be char* in order to call the ifstream current_band_file(current_band) constructor that wants such an argument
You have undefined behavior by using pointers to already destroyed objects.
Simply don't use raw pointers and raw arrays and such stuff yet.
std::string is your friend for strings, std::vector is your friend for arrays.
Example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
auto main()
-> int
{
vector<string> band_names;
for( int i = 1; i <= 103; ++i )
{
band_names.push_back( "band" + to_string( i ) );
}
for( string const& name : band_names )
{
cout << name << endl;
}
}
As a minimal change to you existing code you can change:
current_band[i] = str.c_str();
to:
strcpy(current_band[i], str.c_str());
However, moving away from this mixed C and C++ to more idiomatic C++ (like Cheers and hth. - Alf's answer) will serve you better for the future.
Sticking with things like char[11] over std::string means you're stuck with:
The arbitrary choice of max length 11 even though probably there is no good technical reason for that limit.
Dealing with handling all the details of memory allocation which a proper C++ implementation hides.
The much less natural to read lower level code style.
As a band-aid you could replace:
current_band[i] = str.c_str();
with
if ( str.size() >= 11 )
throw std::runtime_error("string too long");
std::strcpy(current_band[i], str.c_str());
However it would be a much better idea to replace this whole thing with:
std::vector<std::string> current_band(103);
int i = 0;
for (auto &s : current_band)
{
// your sstm stuff, storing to s
}
Here's an alternative way that's a little more robust, readable and more likely to be correct.
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
vector<string> bands;
bands.reserve(103);
for(size_t i = 1 ; i <= 103 ; ++i) {
ostringstream ss;
ss << "band" << i;
bands.emplace_back( ss.str() );
}
for (size_t index = 0 ; index < bands.size() ; ++index) {
cout << index << " : " << bands[index] << endl;
}
return 0;
}
output:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
0 : band1
1 : band2
2 : band3
...
100 : band101
101 : band102
102 : band103
Greeting Everyone
I'm trying to compile and run a multi-language code in C, C++ and fortran using gcc, g++ & f77 respectively in UNIX. My program consists of two parts, one in C, the other in C++. They interface via a main() writen in C+, while the fortran code can be ignored for this case.
I have been having numerous issues with this, most noticabbly a Segmentation Error thats been occuring as I run the executable. The previous two topics of mine have whittled it down, unfortunatly nothing seems to be solving the problem outright other than completely removing any input/output processes in either half of my program, which just isn't feasible.
Accessing public class memory from C++ using C
Output conflicts between C & C++
I need to locate the reason why I recieve Segmentation Errors when I use input/outputs in both parts of my program. All sources compile, all link successfully and I know that each part (C & C++) works when linked alone with no such Segmentation Errors (with modifications to let them work alone of course). I've included all the code that interfaces between the two parts and performs input/output functions.
Any help would be much appriciated.
Makefile
products: SlowDynamic.exe
SlowDynamic.exe: main.o SA.o mersenne.o CFE.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o MA_57.o blas.o MA_57_Depend.o Metis.o
f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -lstdc++ -o SlowDynamic.exe main.o \
SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\
BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
main.o: main.cpp
g++ -c -o main.o main.cpp
SA.o: SA.cpp
g++ -c -o SA.o SA.cpp
mersenne.o: mersenne.cpp
g++ -c -o mersenne.o mersenne.cpp
CFE.o: CFE.c
gcc -c -o CFE.o CFE.c
MA_57.o: MA_57.f
f77 -c -o MA_57.o MA_57.f
blas.o: blas.f
f77 -c -o blas.o blas.f
MA_57_Depend.o: MA_57_Depend.f
f77 -c -o MA_57_Depend.o MA_57_Depend.f
Metis.o: Metis.f
f77 -c -o Metis.o Metis.f
BCs.o: BCs.c
gcc -c -o BCs.o BCs.c
EMatrix.o: EMatrix.c
gcc -c -o EMatrix.o EMatrix.c
Numbering.o: Numbering.c
gcc -c -o Numbering.o Numbering.c
KMatrix.o: KMatrix.c
gcc -c -o KMatrix.o KMatrix.c
Solve.o : Solve.c
gcc -c -o Solve.o Solve.c
clean:
rm *.o Main.exe *.gpi
main.ccp
#include <iostream>
#include "SA.h"
using namespace std;
int main()
{
Initial.Initialize();
Parent.SA(Initial.Write);
system ("PAUSE");
return 0;
}
SA.h
#ifndef SA_H
#define SA_H
#include <vector>
class SimAnneal {
std::vector< std::vector<float> > DensityDomain;
float Solid_Ele_Num, Void_Ele_Num;
float Solid, Void;
double Energy;
double Time;
void Metropolis (double, int, int);
void Next_State (double, int);
double Schedule (double, int);
double ObjFunction ();
void Distribute ();
void Mutate ();
void Convert ();
void PrintDomain ();
void WriteResults (double, double, double, double, double);
public:
int x_max, y_max;
...
std::vector<float> DensityArray;
std::vector<float> EnergyArray;
...
void SA (int);
void Initialize ();
};
extern SimAnneal Initial, Parent, Child, Mutation, Best;
#endif
SA.cpp
include <math.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <vector>
#include "SA.h"
#include "CFE.h"
#include "randomc.h"
using namespace std;
SimAnneal Initial, Parent, Child, Mutation, Best;
...
void SimAnneal::Initialize ()
{
x_max = ReturnX();
y_max = ReturnY();
EnergyArray.resize(x_max*y_max);
DensityArray.resize(x_max*y_max);
...
Energy = ObjFunction();
}
...
void SimAnneal::PrintDomain ()
{
static ofstream OutputFile;
if (!OutputFile.is_open())
{
char FileName [] = "DensityDomain.txt";
OutputFile.open(FileName);
if (!OutputFile)
{
cerr << "Failed to open " << FileName << endl;
exit(EXIT_FAILURE);
}
//cout << "\nGenerating 'DensityDomain.txt'... \n" << endl;
}
for (int y = 0; y < y_max; y++)
{
for (int x = 0; x < x_max; x++)
{
OutputFile << DensityDomain[y][x] << " ";
}
OutputFile << endl;
}
OutputFile.close();
}
void SimAnneal::WriteResults (double i, double T, double x, double y, double z)
{
static ofstream OutputFile;
if (!OutputFile.is_open()) //check is file has been opened
{
char FileName [] = "Results.txt";
OutputFile.open(FileName);
if (!OutputFile)
{
cerr << "Failed to open " << FileName << endl;
exit(EXIT_FAILURE); //abort program
}
//cout << "\nWriting to file in progress... \n" << endl;
OutputFile << "Iterations" << '\t' << "Temperatures" << '\t' << "Sum Strain Energy" << endl; //<< "SwapNum1" << '\t' << "SwapNum2" << '\t' << "Distance" << endl;
OutputFile << endl;
Initial.Time = (int)time(0);
}
OutputFile << i << '\t' << T << '\t' << z << endl; //'\t' << y << '\t' << z << endl;
if (i == N_max || T <= T_abs)
{
Parent.Time = (int)time(0);
OutputFile << endl
<< "Settings: " << endl
<< "Initial Temperature: " << Initial.Temp << endl
<< "Temperature Iterations: " << i << endl
<< "Step Iterations: " << N_step << endl
<< endl
<< "Results: " << endl
<< "Final Temperature: " << Temp << endl
<< "Minimum: " << Energy << endl
<< "Computational Time (s): " << (Parent.Time-Initial.Time) << endl;
OutputFile.close();
}
}
CFE.h
#ifdef __cplusplus
extern "C" {
#endif
int ReturnX ();
int ReturnY ();
void CFE(float density[], float energy[], int Length);
#ifdef __cplusplus
}
#endif
CFE.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BCs.h"
#include "EMatrix.h"
#include "Numbering.h"
#include "KMatrix.h"
#include "fg_types.h"
#include "Solve.h"
int ReturnX ()
{
FILE *infile;
infile = fopen("test05", "r");
int elemX,elemY;
fscanf(infile, "%i %i", &elemX, &elemY);
fclose(infile);
return elemX;
}
int ReturnY () { Same but returns elemY }
void CFE(float density[], float energy[])
{
// Extensive use of fscanf(), printf() & fprintf()
// and the following:
FILE *outfile;
outfile = fopen("File.txt", "w");
if(outfile == NULL){
}
else{
for(n=0;n<8;n++)
{
for(m=0;m<8;m++)
{
fprintf(outfile,"%f",KE[n][m]);
fprintf(outfile,"\t");
}
fprintf(outfile,"\n");
}
}
fclose(outfile);
}
I'd suggest going through your code with a critical eye, and checking out everything that looks even remotely odd.
I'd do it for you but C++ isn't in my rotation at the moment and I'm tripping on false positives. For example, this caught my eye:
if (!OutputFile.is_open())
{
char FileName [] = "DensityDomain.txt";
OutputFile.open(FileName);
if (!OutputFile)
{
cerr << "Failed to open " << FileName << endl;
exit(EXIT_FAILURE);
}
//cout << "\nGenerating 'DensityDomain.txt'... \n" << endl;
}
Half way down you're testing if OutputFile is null, after already calling is_open() and open() on it. It looked to me as if either 1) OutputFile won't be null or 2) you shouldn't be calling methods on it before you test it. But I was wrong.
See what I mean?