', { cookie_domain: 'auto', cookie_flags: 'max-age=0;domain=.tistory.com', cookie_expires: 7 * 24 * 60 * 60 // 7 days, in seconds }); 'Making/빈티지 아두이노 계산기' 카테고리의 글 목록 :: MakerLee's Workspace
728x90

BigNumber는 큰 수 처리에 정말 좋은 라이브러리지만 

초보자를 위한 라이브러리는 아닌 듯.



참조1)

loop 바깥에서

BigNumber a="1234567890.0987654321"; 로 전역선언후 시리얼로 출력해 보면

a=1234567890

로 나온다. 


BigNumber a=1234567890.0987654321; 로 따옴표를 떼면

a=32767로 나옴. 



특이하게도 

BigNumber a='1234567890.0987654321'; 로 홑따옴표를 붙이면

a=12849가 된다. 


BigNumber a="1234567890.0987654321"; 를 loop 안쪽에서 선언하면 

a=1234567890.0987654321 로 제대로 나온다.



BigNumber a = "123556.2342" 형태나 BigNumber a ("143563245.21345245") 형태로 사용해야 한다. 

이 라이브러리는 숫자를 String 취급하는 것 같은데 

그렇다고 실제로 String으로 생각하고 스케치를 하면 오류를 뿜는다. 

문자열 길이를 측정하는 length() 같은 함수를 쓸 수 없다. 




참조2)

LED 디스플레이에 숫자 표기를 정확히 하기 위해서는 숫자의 자리수가 얼마인지 셀 수 있어야 한다.

디스플레이의 자릿수를 벗어나면 정리해 주어야 한다.


숫자의 길이를 측정하려면 
char s = n.toString();  //n을 문자열로 치환하여 s에 저장

length = strlen(s);        //s의 길이를 구하여 length에 저장

같은 식으로 사용해야 한다. 


하지만 이 경우 소수점이 포함되어 계산되므로 

1 -> 1자리수

1.00 -> 4자리수 로 계산되는 문제가 있다.



문제1)

1이상의 수는 어떻게든 처리가 가능하다.

하지만 1 미만의 수는 소수점 때문에 처리가 매우 곤란해진다. 

1 = 1.0000000 과 같이 나오는데 이 경우 0.000000을 어떻게 처리해야 하는가?


문제2)

소수점 이하의 수는 자리수를 어떻게 계산하는가?

1 이상의 수는 10씩 나눠가면서 그 수가 0보다 큰지 아닌지 체크하고
0보다 크면 다시 10 나누는 식으로 자릿수를 계산할 수 있다.

456 
10을 나눈다. = 45.6   (1회)
1보다 큰가? ->yes
10을 나눈다 = 4.56    (2회)
1보다 큰가? ->yes
10을 나눈다 = 0.456  (3회)
1보다 큰가? ->no

3회 반복했으므로 자릿수는 3

하지만 1보다 작은 수는 어떻게 처리해야 하는가?
ex)0.000123


추측1)

123.456을 123 과 0.456으로 분리할 수 있다면 위의 문제들을 해결하기 쉬울 것 같다.
분리하는 방법은?



http://cafe.naver.com/arduinostory/52325


https://arduino.stackexchange.com/questions/1013/how-do-i-split-an-incoming-string



http://cafe.naver.com/arduinostory/27858


728x90
728x90



숫자를 입력할 때마다 한자리씩 늘어나므로 

LED 디스플레이의 커서 위치는 한자리씩 이동해야 합니다. 


length() 함수를 이용해서 커서 위치를 계산해 표시하도록 했습니다.

그랬더니 일정 자릿수가 넘어가면 자릿수가 엉뚱하게 0이 되더군요.

모니터링을 해 봤더니 string 형식의 범위를 벗어나는 문제였습니다. 

BigNumber 사용하느라 생각을 못 했는데 이것도 어찌보면 당연히 발생되는 문제죠.



추가로 생각을 하다 보니 134123456.134526 같이 소수점 자리수가 늘어나면 그에 대한 처리도 해야 합니다. 

숫자를 제대로 체크하려면 BigNumber 함수에서 소수점 이하 자리수를 정확하게 알아야 합니다. 

BigNumber::setScale(3) 으로 하면 100 이 100.000으로 표시됩니다. 



한참 고민을 하다가 자리수를 계산하는 별도의 함수를 만들면 된다는 생각이 들었습니다. 

12341234 를 10씩 나눠가면서 1보다 크거나 같은지 계산하고

1보다 작아지는 순간 이 과정을 몇번 반복했는지 체크하면 자리수를 알아낼 수 있습니다.

반면 소수점 이하 자리수는 이렇게 체크할 수가 없습니다. 

어찌어찌 하면 될 것 같은데.. 머리속에서 맴돌기만 하고 구체화가 안되네요.

이건 조금 더 고민해 봐야겠습니다. 












Grang Total, MR, +-*/ 등의 일반 계산기에서 보여주는 표시를

LED로 표시하도록 했습니다. 

5개의 핀으로 끝내려 했는데 Low BAT 표시등도 넣어야 해서 

6개의 핀으로 3*3 매트릭스를 만들려고 테스트해봤습니다. 


사칙연산 표시는 그냥 디스플레이에 같이 표기해도 되는지라 LED를 넣을지 뺄지 생각중입니다. 

728x90
728x90


VR 기기를 구매해서 한동안 빠져 살았습니다. 

오랫동안 갖고 싶었던 기계인데 너무 비싸서 구매를 주저하고 있었죠.

블프 세일때 저렴하게 올라와서 구매를 결정했습니다. 










그래도 최근 며칠간은 계산기 스케치를 다시 파고들었습니다. 아주 조금이지만요.

BigNumber 라이브러리와 LedDisplay 라이브러리를 조합해서 쓰려니 자료형과 변수형이 머릿속에서 마구 꼬입니다.






키패드 누르는 대로 첫번째 숫자가 자릿수 올라가며 디스플레이되고 있습니다. 

겨우 한걸음 떼었네요 

728x90
728x90

아두이노에서 10여자리 이상의 큰 수나 소수점 이하의 수를 처리하는 문제는

며칠간의 공부 끝에 내 능력으로는 힘들겠구나 하고 결론을 내렸습니다;


그래서 계속 구글링을 했는데 며칠간의 검색 끝에 결국 괜찮은 라이브러리를 찾았습니다.

https://github.com/nickgammon/BigNumber


BigNumber.zip


원문 도큐먼트가 개발자 개인 블로그 에 있길래 혹시 사라질 지 몰라 카피했습니다. 

일단 예문과 결과값을 보면 제가 원하는 부분을 확실히 해결해 줄 수 있을 듯 합니다. 


우린 답을 찾을 것이다. 늘 그랬듯이. 구글에서.


 

Posted byNick Gammon   Australia  (21,293 posts)  [Biography] bio   Forum Administrator
DateTue 31 Jan 2012 09:00 PM (UTC)

Amended on Sat 23 Aug 2014 03:49 AM (UTC) by Nick Gammon

Message
I love big numbers ... they are so ... big!

So in the spirit of getting your Arduino to handle nice, big, numbers I have ported (with pretty minimal effort on my part) the GNU "bc" library to an Arduino library. This can be downloaded from:

http://www.gammon.com.au/Arduino/BigNumber.zip

Just unzip into your "libraries" folder.

Also now available from GitHub:

https://github.com/nickgammon/BigNumber

Factorials


Example sketch:


// BigNumber test: factorials
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum

void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print (i);
    Serial.print ("! = ");
    fact *= i;
    printBignum (fact);
  }

}  // end of setup

void loop () { }



Output from above:


2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000
18! = 6402373705728000
19! = 121645100408832000
20! = 2432902008176640000
21! = 51090942171709440000
22! = 1124000727777607680000
23! = 25852016738884976640000
24! = 620448401733239439360000
25! = 15511210043330985984000000
26! = 403291461126605635584000000
27! = 10888869450418352160768000000
28! = 304888344611713860501504000000
29! = 8841761993739701954543616000000
30! = 265252859812191058636308480000000
31! = 8222838654177922817725562880000000
32! = 263130836933693530167218012160000000
33! = 8683317618811886495518194401280000000
34! = 295232799039604140847618609643520000000
35! = 10333147966386144929666651337523200000000
36! = 371993326789901217467999448150835200000000
37! = 13763753091226345046315979581580902400000000
38! = 523022617466601111760007224100074291200000000
39! = 20397882081197443358640281739902897356800000000
40! = 815915283247897734345611269596115894272000000000
41! = 33452526613163807108170062053440751665152000000000
42! = 1405006117752879898543142606244511569936384000000000
43! = 60415263063373835637355132068513997507264512000000000
44! = 2658271574788448768043625811014615890319638528000000000
45! = 119622220865480194561963161495657715064383733760000000000
46! = 5502622159812088949850305428800254892961651752960000000000
47! = 258623241511168180642964355153611979969197632389120000000000
48! = 12413915592536072670862289047373375038521486354677760000000000
49! = 608281864034267560872252163321295376887552831379210240000000000
50! = 30414093201713378043612608166064768844377641568960512000000000000
51! = 1551118753287382280224243016469303211063259720016986112000000000000
52! = 80658175170943878571660636856403766975289505440883277824000000000000
53! = 4274883284060025564298013753389399649690343788366813724672000000000000
54! = 230843697339241380472092742683027581083278564571807941132288000000000000
55! = 12696403353658275925965100847566516959580321051449436762275840000000000000
56! = 710998587804863451854045647463724949736497978881168458687447040000000000000
57! = 40526919504877216755680601905432322134980384796226602145184481280000000000000
58! = 2350561331282878571829474910515074683828862318181142924420699914240000000000000
59! = 138683118545689835737939019720389406345902876772687432540821294940160000000000000
60! = 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
61! = 507580213877224798800856812176625227226004528988036003099405939480985600000000000000
62! = 31469973260387937525653122354950764088012280797258232192163168247821107200000000000000
63! = 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000
64! = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000
65! = 8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000
66! = 544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000
67! = 36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000
68! = 2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000
69! = 171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000
70! = 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000
71! = 850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000
72! = 61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000
73! = 4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000
74! = 330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000
75! = 24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000
76! = 1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000
77! = 145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000
78! = 11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000
79! = 894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000
80! = 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000
...



Powers



// BigNumber test: powers
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum


void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  BigNumber::begin ();  // initialize library

  Serial.println ("--- powers of 2 ---");
  
  BigNumber a = 2;

  for (int i = 1; i <= 300; i++)
  {
    Serial.print ("2^");
    Serial.print (i);
    Serial.print (" = ");
    BigNumber p = a.pow (i);
    printBignum (p);
  }  // end of for loop

  Serial.println ("--- powers of 3 ---");
  
  a = 3;

  for (int i = 1; i <= 300; i++)
  {
    Serial.print ("3^");
    Serial.print (i);
    Serial.print (" = ");
    BigNumber p = a.pow (i);
    printBignum (p);
  }  // end of for loop

}  // end of setup

void loop () { }


Output from above:


--- powers of 2 ---
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855872
2^58 = 288230376151711744
2^59 = 576460752303423488
2^60 = 1152921504606846976
2^61 = 2305843009213693952
2^62 = 4611686018427387904
2^63 = 9223372036854775808
2^64 = 18446744073709551616
2^65 = 36893488147419103232
2^66 = 73786976294838206464
2^67 = 147573952589676412928
2^68 = 295147905179352825856
2^69 = 590295810358705651712
2^70 = 1180591620717411303424
2^71 = 2361183241434822606848
2^72 = 4722366482869645213696
2^73 = 9444732965739290427392
2^74 = 18889465931478580854784
2^75 = 37778931862957161709568
2^76 = 75557863725914323419136
2^77 = 151115727451828646838272
2^78 = 302231454903657293676544
2^79 = 604462909807314587353088
2^80 = 1208925819614629174706176
2^81 = 2417851639229258349412352
2^82 = 4835703278458516698824704
2^83 = 9671406556917033397649408
2^84 = 19342813113834066795298816
2^85 = 38685626227668133590597632
2^86 = 77371252455336267181195264
2^87 = 154742504910672534362390528
2^88 = 309485009821345068724781056
2^89 = 618970019642690137449562112
2^90 = 1237940039285380274899124224
2^91 = 2475880078570760549798248448
2^92 = 4951760157141521099596496896
2^93 = 9903520314283042199192993792
2^94 = 19807040628566084398385987584
2^95 = 39614081257132168796771975168
2^96 = 79228162514264337593543950336
2^97 = 158456325028528675187087900672
2^98 = 316912650057057350374175801344
2^99 = 633825300114114700748351602688
2^100 = 1267650600228229401496703205376
2^101 = 2535301200456458802993406410752
2^102 = 5070602400912917605986812821504
2^103 = 10141204801825835211973625643008
2^104 = 20282409603651670423947251286016
2^105 = 40564819207303340847894502572032
2^106 = 81129638414606681695789005144064
2^107 = 162259276829213363391578010288128
2^108 = 324518553658426726783156020576256
2^109 = 649037107316853453566312041152512
2^110 = 1298074214633706907132624082305024
2^111 = 2596148429267413814265248164610048
2^112 = 5192296858534827628530496329220096
2^113 = 10384593717069655257060992658440192
2^114 = 20769187434139310514121985316880384
2^115 = 41538374868278621028243970633760768
2^116 = 83076749736557242056487941267521536
2^117 = 166153499473114484112975882535043072
2^118 = 332306998946228968225951765070086144
2^119 = 664613997892457936451903530140172288
2^120 = 1329227995784915872903807060280344576
2^121 = 2658455991569831745807614120560689152
2^122 = 5316911983139663491615228241121378304
2^123 = 10633823966279326983230456482242756608
2^124 = 21267647932558653966460912964485513216
2^125 = 42535295865117307932921825928971026432
2^126 = 85070591730234615865843651857942052864
2^127 = 170141183460469231731687303715884105728
2^128 = 340282366920938463463374607431768211456
2^129 = 680564733841876926926749214863536422912
2^130 = 1361129467683753853853498429727072845824
2^131 = 2722258935367507707706996859454145691648
2^132 = 5444517870735015415413993718908291383296
2^133 = 10889035741470030830827987437816582766592
2^134 = 21778071482940061661655974875633165533184
2^135 = 43556142965880123323311949751266331066368
2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 = 11150372599265311570767859136324180752990208
2^144 = 22300745198530623141535718272648361505980416
2^145 = 44601490397061246283071436545296723011960832
2^146 = 89202980794122492566142873090593446023921664
2^147 = 178405961588244985132285746181186892047843328
2^148 = 356811923176489970264571492362373784095686656
2^149 = 713623846352979940529142984724747568191373312
2^150 = 1427247692705959881058285969449495136382746624
2^151 = 2854495385411919762116571938898990272765493248
2^152 = 5708990770823839524233143877797980545530986496
2^153 = 11417981541647679048466287755595961091061972992
2^154 = 22835963083295358096932575511191922182123945984
2^155 = 45671926166590716193865151022383844364247891968
2^156 = 91343852333181432387730302044767688728495783936
2^157 = 182687704666362864775460604089535377456991567872
2^158 = 365375409332725729550921208179070754913983135744
2^159 = 730750818665451459101842416358141509827966271488
2^160 = 1461501637330902918203684832716283019655932542976
2^161 = 2923003274661805836407369665432566039311865085952
2^162 = 5846006549323611672814739330865132078623730171904
2^163 = 11692013098647223345629478661730264157247460343808
2^164 = 23384026197294446691258957323460528314494920687616
2^165 = 46768052394588893382517914646921056628989841375232
2^166 = 93536104789177786765035829293842113257979682750464
2^167 = 187072209578355573530071658587684226515959365500928
2^168 = 374144419156711147060143317175368453031918731001856
2^169 = 748288838313422294120286634350736906063837462003712
2^170 = 1496577676626844588240573268701473812127674924007424
2^171 = 2993155353253689176481146537402947624255349848014848
2^172 = 5986310706507378352962293074805895248510699696029696
2^173 = 11972621413014756705924586149611790497021399392059392
2^174 = 23945242826029513411849172299223580994042798784118784
2^175 = 47890485652059026823698344598447161988085597568237568
2^176 = 95780971304118053647396689196894323976171195136475136
2^177 = 191561942608236107294793378393788647952342390272950272
2^178 = 383123885216472214589586756787577295904684780545900544
2^179 = 766247770432944429179173513575154591809369561091801088
2^180 = 1532495540865888858358347027150309183618739122183602176
2^181 = 3064991081731777716716694054300618367237478244367204352
2^182 = 6129982163463555433433388108601236734474956488734408704
2^183 = 12259964326927110866866776217202473468949912977468817408
2^184 = 24519928653854221733733552434404946937899825954937634816
2^185 = 49039857307708443467467104868809893875799651909875269632
2^186 = 98079714615416886934934209737619787751599303819750539264
2^187 = 196159429230833773869868419475239575503198607639501078528
2^188 = 392318858461667547739736838950479151006397215279002157056
2^189 = 784637716923335095479473677900958302012794430558004314112
2^190 = 1569275433846670190958947355801916604025588861116008628224
2^191 = 3138550867693340381917894711603833208051177722232017256448
2^192 = 6277101735386680763835789423207666416102355444464034512896
2^193 = 12554203470773361527671578846415332832204710888928069025792
2^194 = 25108406941546723055343157692830665664409421777856138051584
2^195 = 50216813883093446110686315385661331328818843555712276103168
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
...
--- powers of 3 ---
3^1 = 3
3^2 = 9
3^3 = 27
3^4 = 81
3^5 = 243
3^6 = 729
3^7 = 2187
3^8 = 6561
3^9 = 19683
3^10 = 59049
3^11 = 177147
3^12 = 531441
3^13 = 1594323
3^14 = 4782969
3^15 = 14348907
3^16 = 43046721
3^17 = 129140163
3^18 = 387420489
3^19 = 1162261467
3^20 = 3486784401
3^21 = 10460353203
3^22 = 31381059609
3^23 = 94143178827
3^24 = 282429536481
3^25 = 847288609443
3^26 = 2541865828329
3^27 = 7625597484987
3^28 = 22876792454961
3^29 = 68630377364883
3^30 = 205891132094649
3^31 = 617673396283947
3^32 = 1853020188851841
3^33 = 5559060566555523
3^34 = 16677181699666569
3^35 = 50031545098999707
3^36 = 150094635296999121
3^37 = 450283905890997363
3^38 = 1350851717672992089
3^39 = 4052555153018976267
3^40 = 12157665459056928801
3^41 = 36472996377170786403
3^42 = 109418989131512359209
3^43 = 328256967394537077627
3^44 = 984770902183611232881
3^45 = 2954312706550833698643
3^46 = 8862938119652501095929
3^47 = 26588814358957503287787
3^48 = 79766443076872509863361
3^49 = 239299329230617529590083
3^50 = 717897987691852588770249
3^51 = 2153693963075557766310747
3^52 = 6461081889226673298932241
3^53 = 19383245667680019896796723
3^54 = 58149737003040059690390169
3^55 = 174449211009120179071170507
3^56 = 523347633027360537213511521
3^57 = 1570042899082081611640534563
3^58 = 4710128697246244834921603689
3^59 = 14130386091738734504764811067
3^60 = 42391158275216203514294433201
3^61 = 127173474825648610542883299603
3^62 = 381520424476945831628649898809
3^63 = 1144561273430837494885949696427
3^64 = 3433683820292512484657849089281
3^65 = 10301051460877537453973547267843
3^66 = 30903154382632612361920641803529
3^67 = 92709463147897837085761925410587
3^68 = 278128389443693511257285776231761
3^69 = 834385168331080533771857328695283
3^70 = 2503155504993241601315571986085849
3^71 = 7509466514979724803946715958257547
3^72 = 22528399544939174411840147874772641
3^73 = 67585198634817523235520443624317923
3^74 = 202755595904452569706561330872953769
3^75 = 608266787713357709119683992618861307
3^76 = 1824800363140073127359051977856583921
3^77 = 5474401089420219382077155933569751763
3^78 = 16423203268260658146231467800709255289
3^79 = 49269609804781974438694403402127765867
3^80 = 147808829414345923316083210206383297601
3^81 = 443426488243037769948249630619149892803
3^82 = 1330279464729113309844748891857449678409
3^83 = 3990838394187339929534246675572349035227
3^84 = 11972515182562019788602740026717047105681
3^85 = 35917545547686059365808220080151141317043
3^86 = 107752636643058178097424660240453423951129
3^87 = 323257909929174534292273980721360271853387
3^88 = 969773729787523602876821942164080815560161
3^89 = 2909321189362570808630465826492242446680483
3^90 = 8727963568087712425891397479476727340041449
3^91 = 26183890704263137277674192438430182020124347
3^92 = 78551672112789411833022577315290546060373041
3^93 = 235655016338368235499067731945871638181119123
3^94 = 706965049015104706497203195837614914543357369
3^95 = 2120895147045314119491609587512844743630072107
3^96 = 6362685441135942358474828762538534230890216321
3^97 = 19088056323407827075424486287615602692670648963
3^98 = 57264168970223481226273458862846808078011946889
3^99 = 171792506910670443678820376588540424234035840667
3^100 = 515377520732011331036461129765621272702107522001
3^101 = 1546132562196033993109383389296863818106322566003
3^102 = 4638397686588101979328150167890591454318967698009
3^103 = 13915193059764305937984450503671774362956903094027
3^104 = 41745579179292917813953351511015323088870709282081
3^105 = 125236737537878753441860054533045969266612127846243
3^106 = 375710212613636260325580163599137907799836383538729
3^107 = 1127130637840908780976740490797413723399509150616187
3^108 = 3381391913522726342930221472392241170198527451848561
3^109 = 10144175740568179028790664417176723510595582355545683
3^110 = 30432527221704537086371993251530170531786747066637049
3^111 = 91297581665113611259115979754590511595360241199911147
3^112 = 273892744995340833777347939263771534786080723599733441
3^113 = 821678234986022501332043817791314604358242170799200323
3^114 = 2465034704958067503996131453373943813074726512397600969
3^115 = 7395104114874202511988394360121831439224179537192802907
3^116 = 22185312344622607535965183080365494317672538611578408721
3^117 = 66555937033867822607895549241096482953017615834735226163
3^118 = 199667811101603467823686647723289448859052847504205678489
3^119 = 599003433304810403471059943169868346577158542512617035467
3^120 = 1797010299914431210413179829509605039731475627537851106401
3^121 = 5391030899743293631239539488528815119194426882613553319203
3^122 = 16173092699229880893718618465586445357583280647840659957609
3^123 = 48519278097689642681155855396759336072749841943521979872827
3^124 = 145557834293068928043467566190278008218249525830565939618481
3^125 = 436673502879206784130402698570834024654748577491697818855443
3^126 = 1310020508637620352391208095712502073964245732475093456566329
3^127 = 3930061525912861057173624287137506221892737197425280369698987
3^128 = 11790184577738583171520872861412518665678211592275841109096961
3^129 = 35370553733215749514562618584237555997034634776827523327290883
3^130 = 106111661199647248543687855752712667991103904330482569981872649
3^131 = 318334983598941745631063567258138003973311712991447709945617947
3^132 = 955004950796825236893190701774414011919935138974343129836853841
3^133 = 2865014852390475710679572105323242035759805416923029389510561523
3^134 = 8595044557171427132038716315969726107279416250769088168531684569
3^135 = 25785133671514281396116148947909178321838248752307264505595053707
3^136 = 77355401014542844188348446843727534965514746256921793516785161121
3^137 = 232066203043628532565045340531182604896544238770765380550355483363
3^138 = 696198609130885597695136021593547814689632716312296141651066450089
3^139 = 2088595827392656793085408064780643444068898148936888424953199350267
3^140 = 6265787482177970379256224194341930332206694446810665274859598050801
3^141 = 18797362446533911137768672583025790996620083340431995824578794152403
3^142 = 56392087339601733413306017749077372989860250021295987473736382457209
3^143 = 169176262018805200239918053247232118969580750063887962421209147371627
3^144 = 507528786056415600719754159741696356908742250191663887263627442114881
3^145 = 1522586358169246802159262479225089070726226750574991661790882326344643
3^146 = 4567759074507740406477787437675267212178680251724974985372646979033929
3^147 = 13703277223523221219433362313025801636536040755174924956117940937101787
3^148 = 41109831670569663658300086939077404909608122265524774868353822811305361
3^149 = 123329495011708990974900260817232214728824366796574324605061468433916083
3^150 = 369988485035126972924700782451696644186473100389722973815184405301748249
3^151 = 1109965455105380918774102347355089932559419301169168921445553215905244747
3^152 = 3329896365316142756322307042065269797678257903507506764336659647715734241
3^153 = 9989689095948428268966921126195809393034773710522520293009978943147202723
3^154 = 29969067287845284806900763378587428179104321131567560879029936829441608169
3^155 = 89907201863535854420702290135762284537312963394702682637089810488324824507
3^156 = 269721605590607563262106870407286853611938890184108047911269431464974473521
3^157 = 809164816771822689786320611221860560835816670552324143733808294394923420563
3^158 = 2427494450315468069358961833665581682507450011656972431201424883184770261689
3^159 = 7282483350946404208076885500996745047522350034970917293604274649554310785067
3^160 = 21847450052839212624230656502990235142567050104912751880812823948662932355201
...


Who would have thought your humble Arduino could calculate 100 factorial! Or 2 to the power 300! It runs pretty fast too. 

Calculate e



// BigNumber test: calculate e
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum

void setup ()
{
  Serial.begin (115200);
  Serial.println ();

  BigNumber::begin (50);  // max around 160 on the Uno

  // some big numbers
  BigNumber n = 1, e = 1, one = 1;

  int i = 1;
  BigNumber E;  // previous result

  unsigned long start = millis ();
  do
  { 
    E = e;
    n *= i++;  // n is i factorial
    e += one / n;
  }  while (e != E);
  unsigned long time = millis () - start;

  printBignum (e);
  Serial.print (time);
  Serial.println (" mS");
} // end of setup

void loop () { }


Output:


2.71828182845904523536028747135266249775724709369978
629 mS


Theory:

http://en.wikipedia.org/wiki/E_%28mathematical_constant%29

E can be calculated as:


1 + (1/1!) + (1/2!) + (1/3!) ...


That's why the code above is calculating running factorials, and adding the inverse of the factorial to the running total. The code breaks out of the loop when, for the desired number of decimal places, the calculated value doesn't change. That is, at this level of precision, the new amount added does not change the result.

BigNumber class


The C++ BigNumber class handles allocation and deallocation in the constructor and destructor.

For example, factorials can be produced like this:

Code:


  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print (i);
    Serial.print ("! = ");
    fact *= i;
    printBignum (fact);
  }


The normal arithmetic operations are supported (eg. assignment, add, subtract, divide, multiply, modulus). Also things like a++ or a--.

Also comparisons can be done in the natural way.

The only memory allocation you have to worry about is when you get a number to print. Since the library may have to return any size number, it does a malloc to store the number (plus a sign, and decimal point if required). It is up to you to free that string. eg.


// function to display a big number and free it afterwards
void printBignum (BigNumber n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum


An important parameter is the "scale" of the number, which you can set with setScale (n). The scale is effectively the number of decimal places.

For example:


  BigNumber::begin ();  // initialize library

  BigNumber a, b = 2, c;
 
  BigNumber::setScale (0);
  a = BigNumber (1) / BigNumber (3);
  c = b.sqrt ();
  Serial.print ("1/3 = ");
  printBignum (a);
  Serial.print ("sqrt(2) = ");
  printBignum (c);


Output:


1/3 = 0
sqrt(2) = 1


Change the scale to setScale (20) and we get:


1/3 = 0.33333333333333333333
sqrt(2) = 1.41421356237309504880


Change the scale to setScale (100) and we get:


1/3 = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
sqrt(2) = 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727



So clearly the scale is affecting the results. Note that, of course, the larger the scale the slower the calculation and the more memory it will require.

Some caveats



  • Working with large numbers is necessarily slow - the larger the number, or the more decimal places, the slower.

  • Each digit requires a byte of memory, plus some overhead (eg. where the decimal point is) - large numbers will soon gobble up the available memory.

  • Doing a toString also requires memory - a byte per digit, plus the sign, decimal point, and trailing 0x00 byte.

  • An "error" condition inside the library (eg. running out of memory) calls exit(), effectively sending the library into a tight loop.

  • You may need to cast some numbers to avoid "ambiguous" warnings from the compiler.

  • If you only have 2048 bytes of RAM, you clearly need to use a library like this with caution. Running out of memory will be quite likely unless you closely manage the size of your numbers, and how many you have.

  • Memory fragmentation will quite possibly be a problem, particularly if you calculate numbers of different sizes (eg. factorials).


The supplied library has some example code (eg. powers, factorials, sine calculations, e^x, and ln(x) ).

Note that cosine and tangent can effectively be calculated from the sine.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted byNick Gammon   Australia  (21,293 posts)  [Biography] bio   Forum Administrator
DateReply #1 on Tue 22 Jan 2013 05:28 AM (UTC)

Amended on Tue 22 Jan 2013 06:16 AM (UTC) by Nick Gammon

Message
Improvements to printing


Thanks to suggestions from Paul Stoffregen, the library has now been modified to allow you to directly print big numbers.

For example, the Factorials example now looks like this:


// BigNumber test: factorials
#include "BigNumber.h"

void setup ()
{
  Serial.begin (115200);
  while (!Serial) ;
  delay(500);
  Serial.println ();
  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print(i);
    Serial.print("! = ");
    fact *= i;
    Serial.println (fact);
  }

}  // end of setup

void loop () { }


Modified line in bold. This was done by deriving the BigNumber class from the Printable class. This means that you can now print big numbers from any class derived from Stream (eg. Serial, Serial1, etc.).

Also changed slightly to support chips which did not have an exit() function defined in their library.

- Nick Gammon

www.gammon.com.au, www.mushclient.com






728x90
728x90

정수만 갖고 코딩하는것도 초보 수준인데 개념만 살짝 갖고 있는 float 변수형의 16자리수 계산에 대해 개념을 잡으려니 안개처럼 몽실몽실하게 흩어지는군요.





출처: http://elenoa.tistory.com/241

일단 부동소수점이 정확하기 힘들다는 것은 알았습니다.

이진수로 십진수를 계산하기 때문에 어쩔 수 없는 문제지요. 

예전에 인텔도 CPU에서 부동소수점 처리에 결함이 생긴 펜티업 칩 때문에 큰 손실을 본 적이 있습니다(링크)

그리고 저는 고작 10여자리의 부동소수점 때문에 골머리를 썩고 있네요.





아두이노의 레퍼런스를 읽어봅니다





6-7자리의 정확도를 갖고 있다는군요. 

거기다 저는 연산을 해야 하기 때문에 곱셈/덧셈을 할때마다 정확한 자리수가 줄어들겠죠?

생각해보니 이것도 큰 문제네요. 소숫점 이하 50자리까지 정확하다고 해도 그 숫자끼리 몇번 곱하면 곱할때마다 자릿수의 절반씩은 믿을 수 없게 될텐데요





double 을 사용한다고 해도 모자랍니다. 




비슷한 문제를 저만 겪는 건 아닐 것 같아 검색을 해보니 포럼에 비슷한 토론이 많이 있는데 딱히 이거다 하는 해결책은 안보이는군요.





하드웨어의 한계도 있어서 이런 물건도 나오는 듯 합니다. 




그 와중에 GitHub에서 SoftFloat 이라는 아두이노 라이브러리를 찾았는데

description이 하나도 없어서 이해를 못하겠네요;; 헤더파일 보고 해석할 역량은 안되는데 말이죠

https://github.com/mmoller2k/Float64



728x90
728x90


키보드 매트릭스를 테스트하는 중인데 이상하게 2열의 1,2,3 등의 숫자만 입력이 안되더군요






핀에 문제가 있나 하고 핀아웃도 다시 확인하고






배선설정과 실제 스케치간에 연결이 다른부분이 있나 다시 확인해봤습니다. 

문제는 그냥 제가 시리얼로 결과를 확인하고 있다는 것이었지요

Tx 핀으로 입력을 하는데 그걸 시리얼 출력으로 쓰고있으니 당연히 안되는 것이었습니다. 




수정해서 키패드 입력을 LED 디스플레이로 하는건 금방 되었는데

본격적으로 계획을 짜보니 이게 생각보다 난이도가 상당히 높네요.

스케치를 짜려고 보니 생각해야 할 부분이 많습니다.


1. 키패드 매트릭스는 사칙연산 부호 등 때문에 char 형태로 데이터를 주고받음 -> '0' 문자를 숫자로 변경하는건 쉬움. 

2. 25개의 매트릭스 입력에 따라 숫자, 문자 등으로 분류하여 각각 다른 계산을 해야함 -> 역시 어렵진 않을듯. 

3. 계산기의 자리수는 16자리이므로 최대 9999999999999999 까지 표시할 수 있다. 

소수점을 사용해야 하므로 float 변수를 사용하는데 소수점 이하를 표시하려면

앞에 표시될 '0.' 글자를 빼면 소수점 14자리까지 쓸 수 있어야 한다. 

기본적으로 디스플레이에서 float 함수를 쓰면 소수점 2번째 자리까지만 표시되며

"%f" 형을 사용해 float 형을 출력하면 이하 숫자의 오류가 생긴다. 

dtostrf() 함수를 사용하면 3번째이하 자리수를 처리할 수 있지만 

소수점 이하 자리수를 정확히 알고 있는 경우가 아니면 역시 오류가 생긴다 ->갑자기 최종보스 출현한 난이도..;


검색해보니 부동소수점 문제는 원래 어렵더군요.. 

아두이노 계산기 예제라고 나와있는것도 죄다 정수처리만 가능한 간단형 버전이고요.



913425.45 를 출력하면 저렇게 나옵니다.

일단 정확하게 출력하는것도 문제지만 그걸 또 연산처리해야한다는 점이 엄청 골치아프네요

728x90
728x90

아예 AVR 정품 AVR ISP 를 사고싶은 마음도 있지만 

이건 그냥 장비병인 것 같습니다.  쇼핑몰만 둘러보다 포기.




Aliexpress에서 호환 AVRISP MKii 를 샀는데 도착하고 보니 Vcc 에 전원이 안 들어오는 불량품이네요..

일단 Dispute 넣고 그냥 아두이노에 ArduinoISP 넣고 Atmega128에 부트로더를 구웠습니다. 



사실 지난번 ISP 드라이버 안 잡혔을때 이렇게 할까 했지만 미루다 보니 이렇게 됐네요

그냥 아두이노 보드 하나 잡아서 ISP를 따로 만들어 두어야 하나 생각중입니다. 






마찬가지로 지난번에 케이스에 넣었던 FTDI 보드로 업로드했더니 잘 됩니다. 

Blink로 빨간색 LED를 껐다 켰다 해 보았습니다. 






처음에 Atmega128을 쓰려고 했던 이유가 아두이노 핀이 모자랄 것 같아서였습니다

마침 Atmega128 칩도 많이 있는 이유도 있었죠.

그런데 아두이노 보드를 하나하나 체크해 보니 핀이 모자르진 않다는 걸 알게 되었습니다. 

오히려 딱 맞게 쓰고 한두개는 여유있을 정도네요


덕분에 좀 쉽게 갈 수 있을 것 같습니다. 





항상 CNC로 보드를 깎아 버리는걸 선호하지만

이번에는 추가로 주변회로가 어떻게 변할 지 몰라서 

전용 테스트 보드를 만들기에는 문제가 있습니다. 

일반 단면 만능기판에 테스트 보드를 구성하기로 했습니다. 




LED 디스플레이 선을 연결하고 테스트해봤습니다. 

이번 작업은 여기까지입니다.




728x90
728x90


변환보드를 하나 살까 했는데 변환보드 하나에 6000원이라 


에라 하고 이글캐드를 실행해서 보드를 만들고 CNC로 깎았습니다. 


역시나 패턴이 좁아서 실패를 두어번 했네요










USBASP로 부트로더를 심으려고 하는데 안됩니다. 


에러 메세지를 보니 USBASP가 안 잡힌답니다.  


분명 드라이버를 설치했는데 말이죠.


부트로더를 쓸 때마다 최신 운영체제에 대응이 늦어 골때리는 경우가 자주 생기는군요


단순히 시키는 대로 해볼 뿐이라 이런 경우 어떻게 대응해야 하는지 잘 모르고 그대로 스톱됩니다. 






원래 계획대로 쉬프트 레지스터를 쓸지 말지 생각중입니다. 

728x90
728x90

기계식 키보드의 키를 심어서 계산기를 만들면

타격감과 오타율이 적은 계산기를 만들 수 있지 않을까 하던 중에

단순히 기존 계산기를 모딩하지 않고 아예 아두이노로 제작할까 하는 생각이 들었습니다. 






그리고 디스플레이를 전에 구해놓은 HCMS-2912 디스플레이를 이용해서 만들면 

참 이쁜 물건이 될 것 같더군요.







계산기의 키패드는 보통 5열 5행이기 때문에

5*5 키패드 매트릭스가 필요합니다. 








5*5 매트릭스는 10개의 입력핀이 필요하기 때문에

아두이노에서 직접 입력을 받는건 힘들고

74HC165 같은 쉬프트 레지스터를 이용하게 됩니다. 









그래서 74HC165 를 일단 몇개 구매했습니다. 

그리고 아두이노 보드를 계산기 기판에 그대로 심으면 높이 차이가 많이 생겨 케이스를 씌우는 데 무리가 따를 것 같아

아예 계산기 보드에 아두이노를 포함시키려 했습니다. 







그런데 부품박스를 열어보니 ATMEGA168 옆에 ATMEGA128 칩이 보입니다. 






검색해보니(링크) 아두이노로 사용 가능합니다. 







핀 수가 훨씬 많기 때문에 쉬프트 레지스터 없이 바로 사용이 가능하겠네요


결국 ATMEGA168(아두이노)+쉬프트 레지스터 로 가느냐

아니면 ATMEGA128 을 아두이노로 만들어서 쓰느냐 하는 문제인데

ATMEGA128이 쓸데없이 재고가 많은 관계로 이걸 쓰기로 했습니다. 






728x90

+ Recent posts