Slide 1

Slide 1 text

Числата в софтуера Стефан Кънев http://skanev.com/ @skanev BurgasConf 24 август 2013 Бургас

Slide 2

Slide 2 text

Стефан

Slide 3

Slide 3 text

CO

Slide 4

Slide 4 text

Програмист

Slide 5

Slide 5 text

⽃⽄ Ruby, Ruby, Ruby ̆̇㽈

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

❤Programming Languages

Slide 8

Slide 8 text

Ruby, Python, Clojure

Slide 9

Slide 9 text

twitter: @skanev github: skanev blog: http://skanev.com/

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

За какво ще говоря?

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

използваме числа постоянно не разбираме ограниченията не разбираме имплементацията

Slide 15

Slide 15 text

123 + 8 = -125 ???

Slide 16

Slide 16 text

0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 = 5.0 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.999999

Slide 17

Slide 17 text

малко (училищна) математика малко забавни истории повечко практически неща

Slide 18

Slide 18 text

едно нещо

Slide 19

Slide 19 text

не ползвайте float за пари

Slide 20

Slide 20 text

ℕ естествени числа

Slide 21

Slide 21 text

0?, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...

Slide 22

Slide 22 text

0

Slide 23

Slide 23 text

Числата са абстрактни

Slide 24

Slide 24 text

представяне

Slide 25

Slide 25 text

24

Slide 26

Slide 26 text

MLXVI

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

древни гърците са ползвали нещо сходно почват да се изместват в края на Средновековието

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

В компютрите ползваме двоична бройна система

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

0 = 00000 1 = 00001 2 = 00010 3 = 00011 4 = 00100 5 = 00101 6 = 00110 . = .....

Slide 34

Slide 34 text

0 = 00000 1 = 00001 2 = 00010 3 = 00011 4 = 00100 5 = 00101 6 = 00110 . = .....

Slide 35

Slide 35 text

unsigned short unsigned int unsigned long

Slide 36

Slide 36 text

числата са ограничени до 32/64/128 бита...

Slide 37

Slide 37 text

...за “неограничени” числа се ползва BigNumber*

Slide 38

Slide 38 text

8 битов BigNumber bigits: 5, 12, 7 5x2562 + 12x2561 + 7x2560 5x65536 + 12x256 + 7 330759

Slide 39

Slide 39 text

операциите са по-бавни, но числата са “неограничени”

Slide 40

Slide 40 text

някои естествени числа са твърде големи за компютър

Slide 41

Slide 41 text

1082 цифри

Slide 42

Slide 42 text

ℤ цели числа

Slide 43

Slide 43 text

..., -4, -3, -2, -1, 0, 1, 2, 3, 4, ...

Slide 44

Slide 44 text

ℕ< ℤ?

Slide 45

Slide 45 text

0, 1, 2, 3, 4, 5, 6, ... 0, 1, -1, 2, -2, 3, -3, ... ↕ ↕ ↕ ↕ ↕ ↕ ↕

Slide 46

Slide 46 text

Георг Кантор 1845 – 1918

Slide 47

Slide 47 text

представяне

Slide 48

Slide 48 text

byte short int long

Slide 49

Slide 49 text

Вариант 0: един бит за знак

Slide 50

Slide 50 text

5 = 00000101 -5 = 10000101 3 = 00000011 -3 = 10000011

Slide 51

Slide 51 text

5 = 00000101 -5 = 10000101 3 = 00000011 -3 = 10000011

Slide 52

Slide 52 text

Никак не е практично

Slide 53

Slide 53 text

Вариант 1: инвертиране на числото

Slide 54

Slide 54 text

5 = 00000101 -5 = 11111010 3 = 00000011 -3 = 11111100

Slide 55

Slide 55 text

5 = 00000101 -5 = 11111010 3 = 00000011 -3 = 11111100

Slide 56

Slide 56 text

one’s complement

Slide 57

Slide 57 text

не е трудно за имплементация в процесора

Slide 58

Slide 58 text

...но има проблеми

Slide 59

Slide 59 text

0 = 00000000 -0 = 11111111

Slide 60

Slide 60 text

8 бита са 28 - 1 = 255 числа

Slide 61

Slide 61 text

Вариант 2: инвертиране на числото + 1

Slide 62

Slide 62 text

00000101 (5) * * 11111010 inv +1 11111011 (-5)

Slide 63

Slide 63 text

5 = 00000101 -5 = 11111011 3 = 00000011 -3 = 11111101 0 = 00000000 -1 = 11111111

Slide 64

Slide 64 text

събирането на числа с различни знаци е елементарно

Slide 65

Slide 65 text

000011 (3) + 111011 (-5) –––––– 111110 (-2)

Slide 66

Slide 66 text

111101 (-3) + 000101 (5) –––––– 1000010 (2)

Slide 67

Slide 67 text

111101 (-3) + 000101 (5) –––––– 1000010 (2)

Slide 68

Slide 68 text

010000 (16) + 010100 (20) –––––– 100100 (-28)

Slide 69

Slide 69 text

overflow!

Slide 70

Slide 70 text

8 бита: 123 + 8 = -125 ???

Slide 71

Slide 71 text

two’s complement

Slide 72

Slide 72 text

8 бита: -128..127

Slide 73

Slide 73 text

BigNumber лесно се генерализира за цели числа

Slide 74

Slide 74 text

ℚ рационални числа

Slide 75

Slide 75 text

p q ± — p,q ∈ℕ q ≠ 0

Slide 76

Slide 76 text

1/3 13/17 214/103

Slide 77

Slide 77 text

крайни десетични дроби 1/2 = 0.5 1/4 = 0.25 3/5 = 0.6 12/10 = 1.2

Slide 78

Slide 78 text

безкрайни периодични 1/3 = 0.333(3) 1/7 = 0.142857(142857) 1/11 = 0.0909(09)

Slide 79

Slide 79 text

p/q е крайна, когато q се дели само на 2 и 5

Slide 80

Slide 80 text

има тип в повечето езици... ...но рядко се ползва... ...и не е по подразбиране.

Slide 81

Slide 81 text

1 / 3 = ? Ruby: 0 (integer) Python: 0.33333 (float) Clojure: 1/3 (rational)

Slide 82

Slide 82 text

Страхотен тип, на който ще се върнем по-късно

Slide 83

Slide 83 text

кои са повече: целите или рационалните?

Slide 84

Slide 84 text

0, 1, 2, 3, 4, ... ..., -1, ..., 0, ..., 1/4, ..., 1/2, ..., 1, ..., 2, ....

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

Египетски дроби

Slide 87

Slide 87 text

1 2 1 5 1 7 – – – + +

Slide 88

Slide 88 text

1 a 1 b 1 c – – – + + 1 z – + + ... a ≠ b ≠ c ≠ ... ≠ z

Slide 89

Slide 89 text

4 5 1 4 1 20 – – — + + 1 2 – =

Slide 90

Slide 90 text

Няма алгоритъм за оптимално раздробяване

Slide 91

Slide 91 text

В древен Египет са ползвали само такива дроби...

Slide 92

Slide 92 text

...понеже са смятали дроби p/q с p > 1 за грешни...

Slide 93

Slide 93 text

...и са ги наричали “вулгарни дроби”...

Slide 94

Slide 94 text

...гърците също са ги използвали...

Slide 95

Slide 95 text

...чак към Ренесанса започват да се заместват с “вулгарните”.

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

“Естетиката над практичността”

Slide 99

Slide 99 text

Може да се направи паралел с програмирането

Slide 100

Slide 100 text

ℝ реални числа

Slide 101

Slide 101 text

реални = рационални + ирационални

Slide 102

Slide 102 text

безкрайни непериодични дроби

Slide 103

Slide 103 text

1 1 √2

Slide 104

Slide 104 text

√2 = 1.4142135623730950 4880168872420969 8078569671875376 9480731766...

Slide 105

Slide 105 text

π 3.141592653589793238...

Slide 106

Slide 106 text

e 2.718281828459045235...

Slide 107

Slide 107 text

ℕ < ℝ?

Slide 108

Slide 108 text

ℕ < ℝ!

Slide 109

Slide 109 text

непрекъснатостта се нуждае от ирационални числа

Slide 110

Slide 110 text

ирационалните числа са странни

Slide 111

Slide 111 text

знаем малко за тях

Slide 112

Slide 112 text

π+e π.e

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

float

Slide 115

Slide 115 text

Учебниците често казват, че float-овете представят реалните числа

Slide 116

Slide 116 text

Това обяснение е грешно

Slide 117

Slide 117 text

Float-а има един тон особености. Неинтуитивни особености.

Slide 118

Slide 118 text

0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 = 5.0 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.999999

Slide 119

Slide 119 text

9999999999999998 + 1 = 10000000000000000

Slide 120

Slide 120 text

знак експонента мантиса 1 8 23

Slide 121

Slide 121 text

Експонентата е порядъка на дробта: 103, 10-2, 100 1000, 0.01, 1

Slide 122

Slide 122 text

Мантисата (m) са цифри от вида X.XXXXXXX

Slide 123

Slide 123 text

± мантиса x 10експонента

Slide 124

Slide 124 text

Експонента Мантиса Стойност 0 3.14 3.14 x 1 = 3.14 3 2.71 2.71 x 1000 = 2710 -4 1.5 1.5 x 0.0001 = 0.00015

Slide 125

Slide 125 text

Мантисата и експонентата са ограничени в някакъв диапазон

Slide 126

Slide 126 text

Експонента -5 — 5 0.00001 — 10000 Мантиса 3 цифри 0.00 - 9.99 Пример

Slide 127

Slide 127 text

експонента: -5 — 5 мантиса: 0.00 — 9.99 440 = 4.40 x 102 0.7 = 7.00 x 10-1 4210 = 4.21 x 103 0.0101 = 1.01 x 10-2 123000 = 1.23 x 105 0.00143 = 1.43 x 10-3 123001 няма представяне 0.00000012 няма представяне 4210 + 0.0101 няма представяне ...въпреки че двете по отделно имат ...ще трябва върне 4210 или 4420

Slide 128

Slide 128 text

При float, системата е двоична, а не десетична

Slide 129

Slide 129 text

Мантисата е двоична дроб

Slide 130

Slide 130 text

двоично = десетично 0.1 = 0.5 0.01 = 0.25 0.11 = 0.75 0.001 = 0.125 0.011 = 0.375 0.101 = 0.625 0.111 = 0.875

Slide 131

Slide 131 text

Това са единствените дроби, които float може да представя точно

Slide 132

Slide 132 text

a 2b —

Slide 133

Slide 133 text

Единствените такива дроби, ставащи за пари са 0.25, 0.50, 0.75

Slide 134

Slide 134 text

0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 = 5.0 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.999999

Slide 135

Slide 135 text

a 2b — e рационално число

Slide 136

Slide 136 text

Ирационални числа могат да се представят само символно

Slide 137

Slide 137 text

Има и още!

Slide 138

Slide 138 text

Float-овете поддържат две нули: 0.0 и -0.0

Slide 139

Slide 139 text

Float-овете поддържат безкрайности: -∞ и +∞ 1.0 / 0.0 = -Inf

Slide 140

Slide 140 text

Float-овете имат NaN (Not a Number) 0.0 / 0.0 връща* NaN NaN == NaN връща false

Slide 141

Slide 141 text

Float-а дори не е асоциативен: a = 1234.567 b = 45.67844 c = 0.0004 (a + b) + c != a + (b + c)

Slide 142

Slide 142 text

Ако ползвате float за пари: - 0.25, 0.50, 0.75 - имате грешки - имате +∞ и -∞ пари - имате отрицателни нули - имате NaN

Slide 143

Slide 143 text

Float има нишови приложения. Например графика.

Slide 144

Slide 144 text

BigDecimal

Slide 145

Slide 145 text

pi = BigDecimal(“3.14”) e = BigDecimal(“2.71”) pi_times_e = pi * e

Slide 146

Slide 146 text

Пази числата като текстов низ, съдържащ десетична дроб. Буквално.

Slide 147

Slide 147 text

3.14 се пази като “3.14”

Slide 148

Slide 148 text

Този формат също пази само рационални числа (крайни десетични дроби)

Slide 149

Slide 149 text

Операциите са доста по-бавни

Slide 150

Slide 150 text

Събиране, изваждане и умножение са точни и съответно подходящи за пазене на парични суми

Slide 151

Slide 151 text

?

Slide 152

Slide 152 text

а дано, ама надали

Slide 153

Slide 153 text

Делението на BigDecimal числа може да загуби точност

Slide 154

Slide 154 text

x = 1.0 / 3.0 // 0.33333 x * 3.0 // 0.99999

Slide 155

Slide 155 text

За щастие, при работата с пари делението играе роля по-рядко

Slide 156

Slide 156 text

Eдин пример

Slide 157

Slide 157 text

- система за залози на мачове - всеки влиза в системата с Х пари - може да заложи Y пари за мач - цялата сума се разделя пропорционално между позналите - парите в системата са константа

Slide 158

Slide 158 text

Име Сума Залог Васил 10 1 Кирил 30 2 Радо 20 1 Андрей 20 3 Стефан 10 1 Веселин 10 3 Радо, Стефан и Васил печелят Общата сума е 100 лв Радо взема 50 лв Васил и Стефан вземат по 25 лв

Slide 159

Slide 159 text

Ако бяха заложили по равно, всеки трябваше да вземе 100/3лв 100/3 ≈ 33.33

Slide 160

Slide 160 text

Нито float, нито BigDecimal ще поддържат това

Slide 161

Slide 161 text

Rational

Slide 162

Slide 162 text

ℂ комплексни числа

Slide 163

Slide 163 text

i = √-1 i2 = -1

Slide 164

Slide 164 text

имагинерна единица

Slide 165

Slide 165 text

a + bi a, b ∈ ℝ

Slide 166

Slide 166 text

реална част имагинерна част a + bi

Slide 167

Slide 167 text

(a + bi) + (c + di) = = a + c + bi + di = = (a + c) + (b + d)i (a + bi)(c + di) = = ac + adi + cbi + bdi2 = = ac - bd + adi + cbi = = (ac - bd) + (ad + cb)i

Slide 168

Slide 168 text

има три неща за казване

Slide 169

Slide 169 text

Python ги поддържа >>> 1j ** 2 (-1+0j)

Slide 170

Slide 170 text

No content

Slide 171

Slide 171 text

eπi = -1

Slide 172

Slide 172 text

http://xkcd.com/179/

Slide 173

Slide 173 text

No content