Converting two's complement output to signed decimal - c++

I apologize if this question has been answered already but I have not been able to find what I am looking for.
I am working in c++ with an SPI device. The SPI device outputs data in 16 bit words in 2's complement form. I am trying to convert this data into decimal for use with a filter.
I've attached some sample code that asks the user to input a number in twos complement and then outputs the signed decimal version.
#include <iostream>
#include <stdlib.h>
#include <cstdint>
#include <cmath>
#include <bitset>
using std::cout;
using std::endl;
using std::cin;
using std::hex;
using std::dec;
using std::bitset;
int main () {
uint16_t x2=0;
cout<<"Please enter the number you would like to convert from 2's complement. "<<endl;
cin>>x2;
int diff=0x0000-x2;
cout<<"The number you have entered is: "<<dec<<diff<<endl;
return 0;
}
When I run this program and input something like 0x3B4A it always outputs 0. I'm not entirely sure what is going on and I'm very new to c++ so please excuse me if this is a stupid question. Also, please ignore anything extra in the header. This is partof a large project and I couldn't remember what parts of the header go with this specific section of code.
Thanks!
Edit: This is mostly for Ben. After reading your most recent comment I made the following changes but am still simply getting the decimal equivalent of the hexadecimal number I entered
#include <iostream>
#include <stdlib.h>
#include <cstdint>
#include <cmath>
#include <bitset>
using std::cout;
using std::endl;
using std::cin;
using std::hex;
using std::dec;
using std::bitset;
int main () {
int16_t x2=0;
cout<<"Please enter the number you would like to convert from 2's complement. "<<endl;
cin>>hex>>x2;
int flags= (x2>>14) & 3;
int16_t value=(x2 << 2) >> 2;
cout<<"The number you have entered is: "<<dec<<value<<endl;
return 0;
}

I'm not sure it is necessary for the OP's question, but for anybody who is just looking for the formula for converting a 16bit 2's complement unsigned integer to a signed integer, I think a variant of it looks like this (for input val):
(0x8000&val ? (int)(0x7FFF&val)-0x8000 : val)
This amounts to:
if first bit is 1, it is a negative number with all other bits in 2's complement
extract negative part by subtracting off the 0x8000
otherwise the lower bits are just the positive integer value
Probably a good idea to wrap this in a function and do some basic error checking (can also enforce that the input is actually an unsigned 16 bit integer).

You asked cin to read as decimal (by making no format changes) so as soon as it reads the x, which is not a 0-9 digit, it stops, leaving you with zero.
Just add hex to your cin line: cin >> hex >> x2;

The standard library function strtol converts string input to a number, and supports the 0x prefix as long as you pass 0 as the radix argument.
Since int16_t is almost certainly 16-bit two's complement signed, you can just use that.

Related

G++ floating point precision

I have these lines in a C++ program,
auto f = log (FLT_MAX / 4);
printf("%e", f);
cout << f;
The printf result is 8.733654e+1, but cout gives me 87.3365. I checked the 32-bit hex values, they're respectively 0x3f5f94e0 and 0x3f5f94d9, meaning, there seems to be enough precision to represent the value exactly.
Do you know why cout is truncating that floating point value?
Do you know why cout is truncating that floating point value?
Because the default precision C++ streams are set to is 6.
You can change the precision with std::setprecision.
This has nothing to do with g++.
What you should do is this:
#include <limits>
#include <iomanip>
std::cout << std::setprecision(std::numeric_limits<double>::digits10+1) << f;
You can also use long double instead of double to get the maximum precision available.
Documentation
std::setprecision
std::numeric_limits

Reading double from file

For my homework I should read double values from a file and sort them. These are the some of the values. But when read them with my code, when a print it for testing they are written in integer form.
std::ifstream infile (in_File);
double a;
while(infile>>a)
{
std::cout<<a<<std::endl;
}
My doubles are started with 185261.886524 then 237358.956723
And my code print the 185262 then 237359 then so on.
Try adding this at the top of your main():
setlocale(LC_ALL, "C");
This will give your program the "C" locale instead of your local one. I imagine your local one uses "," as a decimal point instead of "." as in your data.
You will need to add #include <clocale> at the top of your file as well.
Edit: then, to get more precision, you can do #include <iomanip> and do this at the top of your program:
std::cout << std::setprecision(20);
setprecision changes how many total digits are printed.
Your problem is not the input, but the output: cout by default prints 6 digits of a double, this is why you see the rounded value 185262, not 185261 as you would expect from incorrect input. Use std::setprecision to increase output precision.
This can happen if on your system your localization settings have a different decimal separator than .. Try add the following include:
#include <locale>
and then use the imbue method:
std::ifstream infile (in_File);
infile.imbue(std::locale("C"));
double a;
while(infile>>a)
{
std::cout<<a<<std::endl;
}

How to work with large numbers when writing and reading a file?

I have written a codes to write my data from one input file to another output file, I used to read all lines of my input file
while (!inputfile.eof())
but in my output file, the last line is missing. So I would like to know, how to prevent this error?
My second question is: for writing data into file, I used
Outputfile.write((char*)&a,sizeof(double));
Outputfile.write((char*)&b,sizeof(double));
here a = 289814.150 and b = 4320978.613 but in the output file, it shows like
289814 4.32098e+006
(value of a is rounded and b value shows with e values) so what is the reason for this and how to fixed this problem?
Here i tried to use cout.setf(ios::fixed);, but if this works for data written on the screen, I don’t know how to fix this to write double data inside my file.
I want to write real values with 3 decimals only in my output file. Please anyone can help thanks.
Okay, based on comments, the intent here has (at least I hope) become reasonably clear: to convert pairs of numbers in text format to binary format, and be able to verify that the converted numbers accurately represent the originals.
There are a number of ways to do that, but the first thing to keep in mind is that no matter what else you do, converting floating point numbers to/from text (decimal) format can and normally will lead to some degree of inaccuracy. The problem is fairly simple: floating point is (normally) done in binary. This means it can only represent fractions in which the denominator is a power of 2 (or a sum of powers of 2). Decimal, obviously enough, uses base 10, so fractions can be composed of a sum of powers of 2 and powers of 5. Any of those that involves a power of 2 (e.g., 0.2) can only be approximated in binary -- pretty much like trying to represent 1/3rd in decimal.
This means your only reasonable choice is to allow some discrepancy between the decimal and binary versions. The best you can hope for is to keep the errors to a minimum. To test for that, what you probably need/want to do is convert the binary floating point back to decimal in the original format, and check whether it's close to the original (e.g., ignore errors in the final digit, at least errors of +/- 1).
The conversion itself should be pretty trivial:
#include <fstream>
int main(int argc, char **argv) {
// checking argc omitted for clarity.
std::ifstream infile(argv[1]);
std::ofstream outfile(argv[2], std::ios::binary);
double a, b;
while (infile >> a && infile >> b) {
outfile.write((char const *)&a, sizeof(a));
outfile.write((char const *)&b, sizeof(b));
}
return 0;
}
Verifying the data isn't nearly so easy. One possibility would be something like this (starting from the two files, one binary and one text):
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
int main(int argc, char **argv) {
std::string text;
std::ostringstream converter;
std::ifstream text_file(argv[1]);
std::ifstream bin_file(argv[2], std::ios::binary);
double bin_value;
while (text_file >> text) {
bin_file.read((char *)&bin_value, sizeof(bin_value));
// the manipulators will probably need tweaking to match original format.
converter << std::fixed << std::setw(3) << std::setprecision(3) << bin_value;
if (converter.str() != text)
;// they're identical
else if (converter.str().substr(0,3) == text.substr(0,3))
;// the first three digits are equal
else
;// bigger error
}
return 0;
}
That's much more likely to need some tweaking to work the way you want, but the general idea should be in the ballpark as long as you're sure the original numbers are all formatted consistently.

Using C++ code in VIsual C++, no errors but some part of the code is just ignored

I'm an absolute beginner to programming and i'm just doing some exercises exercises for the beginning.
First of all, i'm using Visual C++ 2010 to compile C-Code. I just create a new project and choose an empty console application. After that, I create a ressource file named test.c and change in the file properties the elementype to C/C++ Compiler and compile as C++ Code, so that i can use #include <iostream> for the std::cin.get() command. Now the code:
#include <stdio.h>
#include <iostream>
int main()
{
int number1, number2;
int sum;
puts("Enter number 1 please:");
scanf_s("%d",&number1);
puts("Enter number 2 please:");
scanf_s("%d",&number2);
std::cin.get();
std::cin.get(); //(1)
sum = number1 + number2;
printf("The average is %f\n", sum/2);
return 0;
}
Now my problem ist that the "std::cin.get()" command is just ignored. Afer typing in the two numbers the program just stops and the console window closes.
Any idea where the problem is?
I have another question please.
Since my problem with holding the console open is solved (1), now my printf() gives me just zeros as output. I want to have a float number as output but no matter what i type in as number1 and number2 i always get "0.000000".
Since i'm still working on my little program to verify the input before it is accepted, i have another question please.
I want to use the following code just to check the input.
#include <stdio.h>
#include <iostream>
#include <ctype.h>
int main()
{
int number1, number2;
int sum;
puts("Enter number 1 please:");
scanf_s("%d",&number1);
if (isdigit(number1))
{
puts("Enter number 2 please:");
scanf_s("%d",&number2);
}
else
{
puts("Your input is not correct. Enter a number please.");
}
std::cin.get();
std::cin.get();
/*
sum = number1 + number2;
printf("The average is %f\n", sum/2); */
return 0;
}
Well it doensn't work. I type in a digit and my response is "Your input is not...". I have used the search and found the following: Check if User Inputs a Letter or Number in C. Unfortunately the suggestions doesn't help me.
It's not ignored. When you type your second number, then hit enter, it puts your number plus a newline character in the input stream. scanf removes the number, but leaves the newline character alone. When you call cin.get(), since there's a character in the stream, it doesn't wait for your input.
PigBen has already given you a good explanation of where you err. However, I have some additonla points to make about your program which won't fit into a comment:
You are mixing C and C++ input. Why? What's wrong with std::cin >> number1?
When you change number1 to double, you need to remember to change the formatting string in scanf(), too, while with IO streams the compiler will figure out everything for you. With streams and C++' strings, containers and other data structures, it's much harder to do something that compiles, but invokes the dreaded Undefined Behavior at run-time.
Also note that you do not check whether your inputting operations succeed. What happens if I invoke your program, and instead of passing it numbers, I enter non-digits? Never use input from users, files, or other externals sources unverified.
With IO streams, the input operator >> returns (a reference to) the stream, and you can use streams as if they were booleans, so you can do
if(std::cin >> number1)
// input succeeded
or
if( !(std::cin >> number2) ) // note the negation operator !
// input error
to check.
Streams enter a bad state internally after input/output errors. Any further IO operations will fail on a stream that had encountered an error. Therefore, if you want, you can delay input verification until all input operations are done:
std::cout << "Enter number 1 please:";
std::cin >> number1;
std::cout << "Enter number 2 please:";
std::cin >> number2;
if(!std::cin)
// input error
However, remember to always verify input before you first use it.
Note that I didn't check the output for errors. That's because it's hard to imagine something going wrong with output to the console. (And what would you do about it? Print an error message?) However, if you write into a file, remember to check output, too. It's easy for a file operation to go wrong.
In answer to your modified question it is because you are using ints for division. Change int sum to float sum and everything should be fine.
To answer your modified question: you're using the %f printf() format with an int, and that doesn't work. If you want to print out floating-point, you need to pass a double. You could print out (double)sum / 2 or even sum / 2.0, both of which yield doubles. (No, a float doesn't work the same for a variadic function like printf().) As it is, you're passing what is probably a four-byte type and telling printf() to treat it as an eight-byte type of different format, so it's no wonder you're not getting the expected results.
Alternately, you could switch to C++ iostreams, which save you the problem of matching types and knowing the default promotions. You'd still get an integer from sum/2, and that would drop any one-half, but it would be the right result.

Only 2 digits in exponent in scientific ofstream

So according to cplusplus.com when you set the format flag of an output stream to scientific notation via
of.setf(ios::scientific)
you should see 3 digits plus and a sign in the exponent. However, I only seem to get 2 in my output. Any ideas? Compiled on Mac OS using GCC 4.0.1.
Here's the actual code I am using:
of.setf(ios::scientific);
of.precision(6);
for (int i=0;i<dims[0];++i) {
for (int j=0;j<dims[1];++j) {
of << setw(15) << data[i*dims[1]+j];
}
of << endl;
}
and an example line of output:
1.015037e+00 1.015037e+00 1.395640e-06 -1.119544e-06 -8.333264e-07
Thanks
I believe cplusplus.com is incorrect, or at least is documenting a particular implementation - I can't see any other online docs which specifically state the number of exponent digits which are displayed - I can't even find it in the C++ specification.
Edit:
The C++ Standard Library: A Tutorial and Reference doesn't explicitly state the number of exponent digits; but all it's examples display two exponent digits.
It's implementation specific.
This is a bug in M$ implementation AFAIK
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/624b679a4faf03d
I'm getting 3 in MSVC++08 and g++ 4.4.0 with this code:
#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <vector>
typedef float NumberType;
double generate_number(void)
{
return static_cast<NumberType>(std::rand()) / RAND_MAX;
}
void print_number(NumberType d)
{
std::cout << std::setw(15) << d << std::endl;
};
int main(void)
{
std::vector<NumberType> data;
std::generate_n(std::back_inserter(data), 10, generate_number);
// print
std::cout.setf(std::ios::scientific);
std::cout.precision(6);
std::for_each(data.begin(), data.end(), print_number);
}
You can easily change the number type it uses. It gives me three places with both float and double, and the standard says nothing on the actual formatting, so I'd go with mgb's answer.
I have just had a thought - since I am printing floats, why would it display 3 exponent values since the max/min exponent is ~38. I bet if the data array were type double there would be 3.