So I am a bit helpless. I think I understand how to do an addition on IEEE-754 numbers, but I have big problems with subtraction. I have the feeling, that my thoughts are correct, but I want to verify with you guys.
So we have the following two IEEE-754 numbers:
x: 0 1000 0010 100 1000 0000 0000 0000 0000
y: 0 1000 0011 010 1001 0000 0000 0000 0000
Since we have to positive numbers and we want to subtract them, my idea was to take y, invert the mantissa and calculate
x+(-y)
A tutor told me, that that's incorrect, and I have to keep the numbers positive and just subtract them. Why and how he did not tell me.
Can somebody tell me what is the right way to do this?
My thoughts for doing it the x-y way:
extend the exponent from x to 1000 0011
shift the mantissa of x by 1
subtract the two numbers the normal way
OP's 1-2-3 idea is mostly on track, but may have missed the implied bit.
1 Account for the implied bit.
s eeee eeee mmm mmmm mmmm mmmm mmmm mmmm
x: 0 1000 0010 100 1000 0000 0000 0000 0000
y: 0 1000 0011 010 1001 0000 0000 0000 0000
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm
x: 0 1000 0010 1100 1000 0000 0000 0000 0000
y: 0 1000 0011 1010 1001 0000 0000 0000 0000
2 Adjust the smaller, in magnitude, number to form a common exponent. (increment expo, shift "mantissa")
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm extra bits
x: 0 1000 0011 110 0100 0000 0000 0000 0000 0
y: 0 1000 0011 1010 1001 0000 0000 0000 0000
2.5 If signs bit differ, flip the 2nd and perform an add. Yet since the same in this case, not much to do.
3 Subtract smaller from larger.
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm
y: 0 1000 0011 1010 1001 0000 0000 0000 0000
x: 0 1000 0011 110 0100 0000 0000 0000 0000 0
d: 0 1000 0011 0100 0101 0000 0000 0000 0000 0
4 Adjust so MSbit is the implied 1 (Shift "mantissa", decrement exponent).
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm
d: 0 1000 0010 1000 1010 0000 0000 0000 0000
5 Account for reversed subtraction. (Flip sign)
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm
d: 1 1000 0010 1000 1010 0000 0000 0000 0000
6 Round - no value change in this case.
s eeee eeee immm mmmm mmmm mmmm mmmm mmmm
d: 1 1000 0010 1000 1010 0000 0000 0000 0000
7 Remove implied bit to form encoded result.
s eeee eeee mmm mmmm mmmm mmmm mmmm mmmm
d: 1 1000 0010 000 1010 0000 0000 0000 0000
Details of not-a-number, sub-normals, overflow, infinity and rounding left out for brevity.
Note IEEE-754 uses "significand", not "mantissa".
All the methods that produce the correct results are correct. Rounding might be easier to handle by subtracting smaller absolute value from larger and adjusting the sign bits accordingly. Also working with positive numbers only makes it slightly more easier to handle the (optional) implicit one at 1<<23. For negative values the digit would need to be 0xff800000. Other special cases would emerge for negative denormals as well.
Related
I use command tcpdump -x -r input.pcap and have the following tcp packet:
18:05:08.139615 IP 192.168.5.117.12336 > 192.168.5.2.58542: Flags [P.], seq 4484:4604, ack 91, win 5792, options [nop,nop,TS val 3008071469 ecr 2239920620], length 120
0x0000: 4500 00ac a172 4000 4006 0d12 c0a8 0575 E....r#.#......u
0x0010: c0a8 0502 3030 e4ae 1f09 8634 bb24 e0aa ....00.....4.$..
0x0020: 8018 16a0 1372 0000 0101 080a b34b 872d .....r.......K.-
0x0030: 8582 79ec d580 0008 7d08 0000 0000 0000 ..y.....}.......
0x0040: 0000 fd0a ff6f 7308 1200 0a1c 0d0a 0901 .....os.........
0x0050: 1112 0003 1e1f 0c10 010f 0000 0000 0000 ................
0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00a0: 0000 0000 0000 0000 0000 0000
How can I filter byte 8582 at 0x0031? and pipe it to some other command. Does tcpdump has any option to specify bytes to filter from the payload?
I need to filter 2 bytes starting from 0x0030.
tcpdump -lx -r input.pcap | grep 0x0030 | awk '{print $2}'
I was looking to do something similar and settle on using grep to get the line for 0x0030, and then awk to split it by whitespace and print the 2nd field i.e. 8582.
The -l option to tcpdump ensures that output to stdout is immediate.
I am looking to write an equivalent R function based on a C++ snippet I have. See below:
Essentially, I want to decode this:
I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt###
which was converted six bits at a time to printable characters by adding 0x40 to each character as the message was built. The code below describes the process to convert the printable values back to binary. Once the strings have been converted from printable back to binary, they must be reordered using reverse endian conversion.
To:
0010 0100 0000 1000 0000 0000 0000 0000 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1001 0001 1101 1010 0010 1001 0000 0000 1110 1111 0000 0100 0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 1111 0011 1001 1111 0111 0111 1100 0100 0011 0011 0010 1110 0011 0011 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1110 1000 0000 0100 1111 0110 0000 0100 0000 0000 0000 0000 1100 0101 1110 0010 0111 1100 0101 1010 0101 0101 0111 0100 0000 0000
With an R equivalent of this:
/*****************************************************************************/
void Binary_Decode_6bit(char *in_string,unsigned char *out_string)
{
int i,j;
/* DECODE string from 6 bit binary to 8 bit binary */
/* Convert each 4 word group into 3 words */
for (i=0, j = 0; i < strlen(in_string); i += 4)
{
out_string[j++] = ((in_string[i] &0x3f) << 2) | ((in_string[i+1] &0x30) >> 4);
out_string[j++] = ((in_string[i+1] &0x0f) << 4) | ((in_string[i+2] &0x3c) >> 2);
out_string[j++] = ((in_string[i+2] &0x03) << 6) | (in_string[i+3] &0x3f);
}
}
/****************************************************************************
I am hoping to use a R (or even RCpp) function to apply to a rather large list of these messages.
Any help is appreciated!
You can use your C++ (well C) code pretty directly from a function exported to R via Rcpp:
#include <Rcpp.h>
void Binary_Decode_6bit(char *in_string, unsigned char *out_string)
{
int i,j;
/* DECODE string from 6 bit binary to 8 bit binary */
/* Convert each 4 word group into 3 words */
for (i=0, j = 0; i < strlen(in_string); i += 4)
{
out_string[j++] = ((in_string[i] &0x3f) << 2) | ((in_string[i+1] &0x30) >> 4);
out_string[j++] = ((in_string[i+1] &0x0f) << 4) | ((in_string[i+2] &0x3c) >> 2);
out_string[j++] = ((in_string[i+2] &0x03) << 6) | (in_string[i+3] &0x3f);
}
}
// [[Rcpp::export]]
Rcpp::RawVector decode(std::string input) {
if (input.size() % 4 != 0)
Rcpp::stop("input size must be a multiple of 4");
std::vector<unsigned char> tmp(input.size() * 3 / 4);
Binary_Decode_6bit(&input[0], &tmp[0]);
Rcpp::RawVector result(tmp.size());
std::copy(tmp.begin(), tmp.end(), result.begin());
return result;
}
/*** R
decode("I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt####")
decode("I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt###")
*/
Output:
> decode("I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt####")
[1] 24 08 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 91 da 29 00 ef 04 00 00 00 20 00 f3 9f 77 c4 33
[36] 2e 33 00 00 00 00 00 e8 04 f6 04 00 00 c5 e2 7c 5a 55 74 00 00 00
> decode("I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt###")
Error in decode("I#`##B###################IGZJPCoA####B##|y}wqCLnLp######z#SvA###q^I|VeUt###") :
input size must be a multiple of 4
Note that I have added an additional, # at the end of the input string to get the required size. I have not compared the results in detail, but for the sample I have compared your binary representation is identical to my hex representation.
I have been asked by a library to recover some metadata records from some very old (early 1990s) files that can no longer be read by any software and I was wondering if anyone could point me in the right direction for finding out how they are encoded? Here is an arbitrary snippet of one of them:
0014 9c36 0021 7073 2332 0000 0014 9c4d
0022 3478 2332 0000 0014 9c64 0021 7074
2332 0000 0014 9c7b 0022 3479 2332 0000
0014 a3c1 002a edab 2330 0000 0014 a3d8
0022 347a 2332 0000 0014 a3ef 0022 347b
2332 0000 0014 a406 0022 53e9 2332 0000
0014 a41d 0022 347c 2332 0000 0014 a434
0021 87f9 2332 0000 0014 a44b 0020 f046
2332 0000 0014 a462 0027 f928 2332 0000
0014 a479 0020 9e45 2332 0000 0014 a490
0027 68d3 2330 0000 0014 a4a7 0022 44b8
2332 0000 0014 a4be 0027 cf6b 2330 0000
So it is hex of some sort, but I can't seem to decode it to make it make sense. Does anyone have any ideas where I might start? I would preferably like to write a Python script to turn them into some structured metadata format but first I will need to get at something that looks like ASCII perhaps?
Many thanks in advance!
Adam
I'm having some trouble with HttpResponse.TransmitFile under Mono/linux. This code works:
using (var f = System.IO.File.Open(FileName, System.IO.FileMode.Open, FileAccess.Read))
{
f.CopyTo(response.OutputStream);
}
Where as this doesn't: (although it does on Windows)
response.TransmitFile(FileName);
Although in both cases I get back some data, the difference is extreme. Here's the start of the data as it should be:
8950 4e47 0d0a 1a0a 0000 000d 4948 4452
0000 04b0 0000 00a0 0806 0000 001c b895
4700 0000 0473 4249 5408 0808 087c 0864
8800 0000 0970 4859 7300 001b af00 001b
af01 5e1a 911c 0000 0019 7445 5874 536f
6674 7761 7265 0077 7777 2e69 6e6b 7363
6170 652e 6f72 679b ee3c 1a00 0020 0049
4441 5478 9cec bd79 7454 c799 37fc bbbd
492d b5f6 7d97 90d8 1108 3060 b3d8 98dd
3660 6ce2 78c1 d8ce 624f 66be 64f2 bd99
9ce4 cb99 c9c9 36f1 c439 4eec c964 9cc5
9937 f19b 38c9 6499 378e 63c7 3678 5f00
6302 189b cd6c 0281 d086 d46a f5be dcef
0f51 5777 a9ba b76e 770b 845d bf73 38b4
... (109270 bytes total)
but this is what I get:
3161 6164 360d 0a89 504e 470d 0a1a 0a00
0000 0d49 4844 5200 0004 b000 0000 a008
0600 0000 1cb8 9547 0000 0004 7342 4954
0808 0808 7c08 6488 0000 0009 7048 5973
0000 1baf 0000 1baf 015e 1a91 1c00 0000
1974 4558 7453 6f66 7477 6172 6500 7777
772e 696e 6b73 6361 7065 2e6f 7267 9bee
3c1a 0000 2000 4944 4154 789c ecbd 7974
54c7 9937 fcbb bd49 2db5 f67d 9790 d811
0830 60b3 d898 dd36 606c e278 c1d8 ce62
4f66 be64 f2bd 999c e4cb 99c9 c936 f1c4
394e ecc9 649c c599 37f1 9b38 c964 9937
8e63 c736 785f 0063 0218 9bcd 6c02 81d0
86d4 6af5 bedc ef0f 5157 77a9 bab7 6e77
... (109286 bytes total)
It looks like some sort of encoding issue, but I'm stumped as to what it could be or how to fix it.
It starts with 3161 6164 360d 0a, which is a hex number (0x1aad6 or 109270 in decimal, which is the is the size of your file) followed by a CRLF. Looks like chunked encoding to me.
Your HTTP Headers should also contain Transfer-Encoding: chunked.
That's nothing to worry about, the server will get the correct data.
I am having difficulty understanding why the following binary subtraction gives the result that it does. I keep getting a different answer. I am trying to compute 0.1-x such that x is 0.00011001100110011001100. The answer should be 0.000000000000000000000001100[1100]...(1100 keeps repeating) When i do it, I keep getting 1100 in the very beginning.
What am I not doing correctly?
I think that your expected answer is wrong. Here's my solution. I'll group the bits into nybbles so that it would look readable.
0.1000 0000 0000 0000 0000 0000 <- added zero to the rightmost to fill in the nybble
- 0.0001 1001 1001 1001 1001 1000 <- added zero to the rightmost to fill in the nybble
_________________________________
Get the 2's complement of 0.0001 1001 1001 1001 1001 1000.
1.1110 0110 0110 0110 0110 0111 (1's complement)
+ 0.0000 0000 0000 0000 0000 0001
_________________________________
1.1110 0110 0110 0110 0110 1000 (2's complement)
Add the 2's complement to 0.1.
0.1000 0000 0000 0000 0000 0000
+ 1.1110 0110 0110 0110 0110 1000
_________________________________
10.0110 0110 0110 0110 0110 1000
Since the overflow is 1, disregard it. It just signifies that the final answer is a positive number since 0.1 is larger than 0.0001 1001 1001 1001 1001 1000. Therefore, the final answer is 0.011001100110011001101000.