16 bit hex into 14 bit signed int python?
<p>I get a 16 bit Hex number (so 4 digits) from a sensor and want to convert it into a signed integer so I can actually use it.
There are plenty of codes on the internet that get the job done, but with this sensor it is a bit more arkward.</p>

<p>In fact, the number has only 14 bit, the first two (from the left) are irrelevant.
I tried to do it (in Python 3) but failed pretty hard.
Any suggestions how to "cut" the first two digits of the number and then make the rest a signed integer? 
The Datasheet says, that E002 should be -8190 ane 1FFE should be +8190.</p>

<p>Thanks a lot!</p>

<p>Let's define a conversion function:</p>

<pre><code>&gt;&gt;&gt; def f(x):
...    r = int(x, 16)
...    return r if r &lt; 2**15 else r - 2**16
... 
</code></pre>

<p>Now, let's test the function against the values that the datahsheet  provided:</p>

<pre><code>&gt;&gt;&gt; f('1FFE')
8190
&gt;&gt;&gt; f('E002')
-8190
</code></pre>

<p>The usual convention for signed numbers is that a number is negative if the high bit is set and positive if it isn't.  Following this convention, '0000' is zero and 'FFFF' is -1.  The issue is that <code>int</code> assumes that a number is positive and we have to correct for that:</p>

<ul>
<li><p>For any number equal to or less than <code>0x7FFF</code>, then high bit is unset and the number is positive.  Thus we return <code>r=int(x,16)</code> if r&lt;2**15.</p></li>
<li><p>For any number <code>r-int(x,16)</code> that is equal to or greater than <code>0x8000</code>, we return <code>r - 2**16</code>.</p></li>
<li><p>While your sensor may only produce 14-bin data, the manufacturer is following the standard convention for 16-bit integers.</p></li>
</ul>

<h3>Alternative</h3>

<p>Instead of converting <code>x</code> to <code>r</code> and testing the value of <code>r</code>, we can directly test whether the high bit in <code>x</code> is set:</p>

<pre><code>&gt;&gt;&gt; def g(x):
...    return int(x, 16) if x[0] in '01234567' else int(x, 16) - 2**16
... 
&gt;&gt;&gt; g('1FFE')
8190
&gt;&gt;&gt; g('E002')
-8190
</code></pre>

<h3>Ignoring the upper bits</h3>

<p>Let's suppose that the manufacturer is not following standard conventions and that the upper 2-bits are unreliable.  In this case, we can use modulo, <code>%</code>, to remove them and, after adjusting the other constants as appropriate for 14-bit integers, we have:</p>

<pre><code>&gt;&gt;&gt; def h(x):
...    r = int(x, 16) % 2**14
...    return r if r &lt; 2**13 else r - 2**14
... 
&gt;&gt;&gt; h('1FFE')
8190
&gt;&gt;&gt; h('E002')
-8190
</code></pre>

python cut bits data-conversion