Skip to content

Commit 3ce3391

Browse files
committed
more clarification
1 parent 16633a0 commit 3ce3391

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

notes/2023-11-21.md

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,12 @@ and
259259

260260

261261
would represent:
262-
$$ (-1)*0 + \left(1 + 0\cdot 2^{-1} + 1\cdot 2^{-2} + \ldots + 0\cdot 2^{-51} + 0\cdot 2^{-52} \times \right) 2^{1023-1023} = 0 + (1 + \frac{1}{2}) \times 2^0 = 1.5 \times 1 = 1.25 $$
262+
$$ (-1)*0 + \left(1 + 0\cdot 2^{-1} + 1\cdot 2^{-2} + 0\cdot 2^{-3} + \ldots + 0\cdot 2^{-51} + 0\cdot 2^{-52} \times \right) 2^{1023-1023} = 0 + (1 + \frac{1}{2}) \times 2^0 = 1.5 \times 1 = 1.25 $$
263263
<!-- #endregion -->
264264

265265
You can see this visually using [float exposed](https://float.exposed/0x3ff4000000000000)
266266

267-
```{important}
267+
```{tip}
268268
the URL of that link is to `float.exposed/0x3ff4000000000000`
269269
270270
`3ff4000000000000` is the number we want to view in hex. Since the first 12 bits of the 64bit nubme are the sign and expontend, the first 3 characters represent those then the remaining 13 characters represent the 52 bits of the fraction.
@@ -277,12 +277,14 @@ So `3ff=011111111` and then 4000000000000=01000000000000000000000000000000000000
277277
To see more examples of numbers doing surprising and interesting things try [memory spy](https://memory-spy.wizardzines.com/game#)```
278278
````
279279

280-
Python can give you the float representation of
280+
Python can give you the hex representation of a float:
281281

282282
```{code-cell} python
283283
float.hex(1.25)
284284
```
285285

286+
This matches what we saw above, but it takes some re-arranging, this is a good practice.
287+
286288

287289

288290

@@ -357,23 +359,20 @@ We want to use exactly 53 bits to represent $J$ because it needs to be represent
357359

358360
We can use this to find what $N$ needs to be first.
359361

360-
we want $J \approx \frac{2^N }{10}$ to be greater than or equal to $2^{52}$ and less than $2^{53}$, or equivalently
361-
362-
362+
we want $J \approx \frac{2^N }{10}$ to be greater than or equal to $2^{52}$ and less than $2^{53}$, or equivalently:
363363

364364
$$ 2^{52} <= \frac{2^N }{10} < 2^{53} $$
365365

366366

367367

368368
Since $10 =8+2 = 2^3 +2^1$ then $2^3<10<2^4$
369-
We can also bound our quantity like this:
369+
We can change the bounds of our inequality above.
370370

371371
$$ \frac{2^N }{16} = \frac{2^N }{2^4} < \frac{2^N }{10} < \frac{2^N }{2^3} = \frac{2^N }{8} $$
372372

373373
and then we can re-write the middle comparison like this:
374374

375375

376-
377376
$$ 2^{N-4} < \frac{2^N }{10} < 2^{N-3} $$
378377

379378

@@ -385,9 +384,9 @@ and then we can re-write the middle comparison like this:
385384

386385

387386

388-
then best $N$ is 56, but we can check it.
389-
387+
then best $N$ is 56, because that will make the upper inequality the same as the lower one.
390388

389+
We can also check tha this does what we want.
391390

392391
```{code-cell} python
393392
2**52 <= 2**56 //10 < 2**53
@@ -399,22 +398,21 @@ Now we can get the number we will use for $J$. So far, mathematically, we would
399398

400399
$$J \approx \frac{2^{56}} {10}$$
401400

402-
but we need to find an integer value, so we divide that out and separate the `q`uotient and `r`emainder
401+
but we need to find an integer value, so we divide and separate the `q`uotient and `r`emainder.
403402

404403
```{code-cell} python
405404
q,r = divmod(2**56,10)
406405
```
407406

408407

409-
Then we check the remainder to decide if we should round up by 1 or not.
408+
Next we check the remainder to decide if we should round up by 1 or not.
410409

411410
```{code-cell} python
412411
r
413412
```
414413

415414

416-
$ 6 > 5 = \frac{10}{2}$ so we round up
417-
415+
$ 6 > 5 = \frac{10}{2}$ so we round up. Since the remainder is more than half of the divisor it is closer to the next number up, so we increment.
418416

419417

420418
```{code-cell} python
@@ -424,7 +422,7 @@ J
424422

425423

426424

427-
then we chan check the length in bits of that number
425+
then we can check the length in bits of that number
428426

429427
Python can print it for us:
430428
```{code-cell} python
@@ -440,6 +438,20 @@ len(bin(J))-2
440438
Which is 53 as expected! To get the actual number we represent in the fraction part we want to drop the left most bit.
441439

442440

441+
To actually represent our final number, we want to drop the left most bit. Remember, we found the number that gets represented including the additional 1 outside of the sum of the bits in the fraction.
442+
443+
```{code-cell} python
444+
significand = J-2**52
445+
significand
446+
```
447+
448+
or in binary:
449+
```{code-cell} python
450+
bin(significand)
451+
```
452+
453+
454+
443455
Now, we go back to the $e$. We need $52-e+1023 = 56$ so we solve to find
444456
$$e = 52+1023-56$$
445457

@@ -449,7 +461,19 @@ e = 52-56+1023
449461
e
450462
```
451463

464+
So our representation of .1 would be:
465+
466+
```{code-cell} python
467+
exp_bin = bin(e)[2:]
468+
sig_bin = bin(significand)[2:]
469+
'0' + exp_bin + sig_bin
470+
```
471+
472+
dropping the first two characters is because those are the 0b syntax indicator, not the actual binary.
473+
474+
452475

476+
[see on float exposed](https://float.exposed/0x3fb999999999999a)
453477

454478
Python doesn't provide a binary reprsentation of floats, but it does provide a hex representation.
455479

0 commit comments

Comments
 (0)