#include "BigInteger.h" #include // setw »ç¿ë namespace { const BigInteger _One(1); const BigInteger _Zero(0); const unsigned long N = 32; // blk ÇÑºí·°ÀÇ ºñÆ® ±æÀÌ /* * radix_aºÎÅÍ radix_d±îÁö´Â * ÀÔ·Â, Ãâ·Â ÇÔ¼ö¿¡¼­ »ç¿ëÇϱâ À§ÇØ ÀÛ¼ºÇÏ¿´°í * ³ª¿À°Ô µÈ ÀÌ·ÐÀûÀÎ ¹è°æÀº ´ÙÀ½°ú °°½À´Ï´Ù. * * ÀϹÝÀûÀ¸·Î 2Áø¼ö·Î µÇÀÖ´Â °ªÀ» 10Áø¼ö·Î * Ãâ·ÂÇϱâ À§Çؼ­´Â 2Áø¼ö °ªÀ» bcd·Î ¹Ù²Û ÈÄ, Ãâ·ÂÇÕ´Ï´Ù. * (¿©±â¿¡ ´ëÇÑ ³»¿ëÀº ÀÎÅͳݿ¡¼­ * bcd, binary to bcd, shift and add 3, double dabble * µîÀÇ °Ë»ö¾î·Î ´Ù¾çÇÑ Á¤º¸¸¦ ¾òÀ¸½Ç ¼ö ÀÖ½À´Ï´Ù.) * ¿©±â¼­µµ ¹°·Ð °°Àº ¹æ¹ýÀ» »ç¿ëÇÏ¿© Ãâ·Â, ÀÔ·ÂÀ» Çϸç * Á» ´õ ÀϹÝÀûÀÌ°í È®ÀåµÈ Á¤¸®¸¦ »ç¿ëÇÕ´Ï´Ù. * * "binary to bcd"("2Áø¼ö¸¦ bcd·Î") * bcd¶õ °£´ÜÈ÷ 10Áø¹ý ¹è¿­ÀÔ´Ï´Ù. * 0ºÎÅÍ 9¶ó´Â ¼ýÀÚ¸¦ ³ªÅ¸³»±â À§Çؼ­´Â * ÃÖ¼Ò 4ºñÆ®°¡ ÇÊ¿äÇϸç(2^4=16) 4ºñÆ®·Î 10Áø¹ýÀÇ * ÇÑÀÚ¸®¸¦ ³ªÅ¸³½´Ù´Â °ÍÀÌ bcdÀÔ´Ï´Ù. * Áï, bcd·Î ¹Ù²Û´Ù´Â ¸»Àº 2Áø¼ö °ªÀ» 10Áø¹ýÀÇ ¹è¿­·Î ¹Ù²Û´Ù´Â À̾߱âÀ̸ç * ÀÌ°ÍÀ» ÀϹÝÈ­ Çغ»´Ù¸é ´ÙÀ½°ú °°½À´Ï´Ù. * * "binary to arbitrary radix"("2Áø¼ö¸¦ ÀÓÀÇÀÇ Áø¹ýÀ¸·Î") * 2Áø¼ö °ªÀ» nÁø¹ýÀ¸·Î Ãâ·Â ÇÏ°íÀÚ ÇÑ´Ù¸é * nÁø¹ýÀÇ ¹è¿­·Î ¹Ù²Ù¾îÁÖ¸é µË´Ï´Ù. * ±×·³ ¿©±â¼­ nÁø¹ý ¹è¿­ÀÇ ¿ø¼Ò´Â ÃÖ¼Ò ¸îºñÆ®°¡ ÇÊ¿äÇÒ±î¿ä? * ¿ì¸®°¡ Ç¥ÇöÇÏ°íÀÚ ÇÏ´Â Áø¹ýÀº * 2~36»çÀÌÀÇ Áø¹ýÀÔ´Ï´Ù. * ¿©±â¼­ 36Áø¹ýÀÌ ÇÑÀÚ¸®´ç ÇÊ¿äÇÑ ºñÆ®¼ö°¡ Á¦ÀÏ ¸¹½À´Ï´Ù. * ÃÖ¼Ò 6ºñÆ®°¡ ÇÊ¿äÇÕ´Ï´Ù.(2^6=64) * ¿ì¸®°¡ »ç¿ëÇÒ ¼ö Àִ ŸÀÔ Áß °¡Àå ÀÛÀº °ÍÀº 1¹ÙÀÌÆ®(8ºñÆ®)À̸ç * 36Áø¹ýÀ̶ó°í Ä¡¸é ÇÑ ÀÚ¸®´ç 2ºñÆ®(8-6=2)¸¦ ºñÈ¿À²ÀûÀ¸·Î »ç¿ëÇÕ´Ï´Ù. * Á¤¸®ÇÏÀÚ¸é bcd¸¦ ÀϹÝÈ­ ÇÑ °ÍÀº * 2Áø¼ö °ªÀ» nÁø¹ýÀ¸·Î Ãâ·ÂÇÏ´Â ¹æ¹ýÀ̸ç * nÁø¹ý ¹è¿­À» »ç¿ëÇÏ¿© ÇÑÀÚ¸®¾¿À» Ç¥ÇöÇÑ´Ù´Â °ÍÀÔ´Ï´Ù. * ±×·¯³ª ÀÌ·¸°Ô ÇÑÀÚ¸®¾¿ ²÷¾î¼­ ³ªÅ¸³»¸é * Å«¼ö¸¦ ÀÔ,Ãâ·ÂÇØ¾ß ÇÏ´Â »óȲ¿¡¼­ * ¸Þ¸ð¸®°¡ ºñÈ¿À²ÀûÀ¸·Î ³¶ºñ µÉ »Ó¸¸ ¾Æ´Ï¶ó * 1¹ÙÀÌÆ®¿Í °°ÀÌ ÀÛÀº ºñÆ®¸¦ Á¢±ÙÇÏ´Â ¿¬»êÀ» ÇÏ¿© ¼Óµµµµ ³ªÁö ¾Ê½À´Ï´Ù. * µû¶ó¼­ ¿©±â¼­ ÇÑ¹ß ´õ ³ª¾Æ°¡ * 32ºñÆ®¿¡ ÃÖÀûÈ­ ½Ãŵ´Ï´Ù.(cpu ºñÆ®¼ö) * * "binary to arbitrary radix in 32bits("2Áø¼ö¸¦ ÀÓÀÇÀÇ Áø¹ýÀ¸·Î(32ºñÆ® ÃÖÀûÈ­)")" * ÀÏ´Ü, Áø¹ý º¯È¯ À̾߱⸦ »ì¦ ÇÏ°Ú½À´Ï´Ù. * 9Áø¹ýÀ¸·Î 17À» 3Áø¹ýÀ¸·Î ¹Ù²Û´Ù¸é ¾î¶»°Ô ±¸ÇÒ±î¿ä? * 9´Â 3ÀÇ 2½ÂÀÔ´Ï´Ù. Áï, 9Áø¹ýÀÇ ÇÑÀÚ¸®´Â 3Áø¹ýÀ¸·Î µÎÀÚ¸®¶ó´Â ¸»ÀÌ µË´Ï´Ù. * (27Áø¹ýÀ» 3Áø¹ýÀ¸·Î ³ªÅ¸³½´Ù¸é 27(3 ^ 3)Áø¹ýÀÇ ÇÑÀÚ¸®´Â 3Áø¹ýÀ¸·Î 3ÀÚ¸®°¡ µË´Ï´Ù.) * 9Áø¹ý 1Àº 3Áø¹ýÀ¸·Îµµ 1, 9Áø¹ý 7Àº 3Áø¹ýÀ¸·Î 21ÀÔ´Ï´Ù. * Áï, 3Áø¹ýÀ¸·Î 121ÀÌ µË´Ï´Ù. * ¿©±â¼­ ¾Ë ¼ö ÀÖ´Â °ÍÀº Áø¹ý º¯È¯¿¡ ÀÖ¾î * nÁø¹ýÀ» rÁø¹ýÀ¸·Î º¯È¯ÇÑ´Ù°í ÇÏ¿´À» ¶§(n > r) * nÁø¹ýÀÌ rÁø¹ýÀÇ Áö¼ö½ÂÀ¸·Î ³ªÅ¸³¾ ¼ö ÀÖ´Ù¸é(=> n == r ^ x) * nÁø¹ýÀÇ rÁø¹ý º¯È¯Àº Ãß°¡ÀûÀÎ ³ª´°¼À ¿¬»ê ¾øÀ̵µ * °¢ ÀÚ¸®¸¦ ÂÉ°³´Â °Í¸¸À¸·Î º¯È¯ÀÌ °¡´ÉÇÏ´Ù´Â °ÍÀÔ´Ï´Ù. * ÀÚ ÀÌÁ¦, ¹«¾ùÀ» ÇØ¾ß ÇÒÁö °¨ÀÌ ¿À½Ã³ª¿ä? * nÀÇ x½Â Áø¹ýÀ¸·Î ¼ýÀÚ¸¦ ÀúÀå ÇÑ ÈÄ, * n ^ x½Â ÇÑÀÚ¸®¸¦ x°³ÀÇ ÀÚ¸®·Î ÂÉ°³´Â Àü·«À» ¾²°Ú´Ù´Â °Ì´Ï´Ù! * ±×¸®°í ÀÌ Àü·«À» 32ºñÆ®¿¡ ÃÖÀûÈ­ ½ÃÅ°´Â °ÍÀÔ´Ï´Ù! * ±×·³ °ú¿¬ nÁø¹ýÀÇ ¸î ½Â Áø¹ýÀ» ½á¾ß ÇÒ±î¿ä? * ¿©±â¿¡¼­ radix_a¸¦ ±¸ÇÑ ÀÌÀ¯°¡ ³ª¿É´Ï´Ù. * ±× ½ÄÀº ´ÙÀ½°ú °°½À´Ï´Ù. * 2^32 >= n ^ x (nÁø¹ýÀÇ x½Â)À» ¸¸Á·ÇÏ´Â Á¦ÀÏ Å« x * 32ºñÆ®·Î ³ªÅ¸³¾ ¼ö ÀÖ´Â nÁø¹ýÀÇ ÃÖ´ë ½ÂÀ» ±¸ÇÏ´Â ½ÄÀÔ´Ï´Ù. * ÀÌ°ÍÀ» radix_a¶ó´Â ¹è¿­¿¡ ÀúÀåÇØ µÎ¾ú½À´Ï´Ù. * ±×¸®°í n ^ x °ªÀ» radix_b¶ó´Â ¹è¿­¿¡ ÀúÀåÇØ µÎ¾ú±¸¿ä. * ¿©±â±îÁö¸¦ Á¤¸®Çغ¸¸é * 2Áø¼ö °ªÀ» nÁø¹ýÀ¸·Î º¯È¯, Ãâ·ÂÇϴµ¥ ÀÖ¾î * 32ºñÆ®¿¡ ÃÖÀûÈ­ ½ÃÅ°±â À§Çؼ­ * 2Áø¼ö °ªÀ» nÁø¹ýÀÇ x½Â Áø¹ýÀ¸·Î °ªÀ» º¯È¯ÇÑ ÈÄ, * nÁø¹ýÀÇ x½Â Áø¹ýÀÇ °¢ ÀÚ¸®¸¦ nÁø¹ý x°³·Î ÂÉ°³´Â ½ÄÀ¸·Î * Ãâ·ÂÇÑ´Ù¸é ÀÌ°ÍÀº 2Áø¼ö °ªÀ» nÁø¹ýÀ¸·Î Ç¥ÇöÇÏ´Â °Í°ú °°´Ù! * ¶ó°í Á¤¸® ÇÒ ¼ö ÀÖ½À´Ï´Ù. * ÈÄ... ÀÌÁ¦ ¾î¶»°Ô ÇØ¾ß ÇÏ´ÂÁö ¹æÇâÀº Á¤Çß½À´Ï´Ù. * ±Ùµ¥ Áß°£ °úÁ¤ÀÌ ¼³¸íµÇÁö ¾Ê¾Ò½À´Ï´Ù. * 2Áø¼ö °ªÀ» n ^ x Áø¹ýÀ¸·Î ÀúÀåÇÑ´Ù°í Çߴµ¥ * ¾î¶»°Ô ÀúÀåÇÒ°ÍÀΰ¡ ÇÏ´Â °Ì´Ï´Ù. * * "Shift and Add 3(Double Dabble) algorithm" * Áø¹ý º¯È¯ ÇÏ´Â ¹æ¹ý ¾Æ½Ã³ª¿ä? * 10Áø¼ö¸¦ 8Áø¹ýÀ¸·Î ¹Ù²Ü·Á¸é * 8·Î ³ª´©¾î¼­ ±× ³ª¸ÓÁöµéÀ» ¿ª¼øÀ¸·Î ¾²¸é µÈ´Ù°í ¹è¿ü½À´Ï´Ù. * Áï, ¾î´À ¼ö¸¦ nÁø¹ýÀ¸·Î ¹Ù²Û´Ù¸é ±× ¼ö¸¦ nÀ¸·Î ³ª´©¾î¼­ * ±× ³ª¸ÓÁöµéÀ» ¿ª¼øÀ¸·Î ¾²¸é µË´Ï´Ù. * ÀÌ°ÍÀ» À§ÀÇ 32ºñÆ® ÃÖÀûÈ­ÀÇ °³³ä¿¡ Àû¿ëÇÏ´Ù¸é * Ãâ·ÂÇÏ°íÀÚ ÇÏ´Â ¼ýÀÚ¸¦ n ^ x·Î ³ª´©¾î * ±× ³ª¸ÓÁö¸¦ ¿ª¼øÀ¸·Î ÀúÀåÇϸé * 2Áø¼ö °ªÀ» n ^ xÁø¹ýÀ¸·Î ¹Ù²Ù¾î ÀúÀåÇÒ ¼ö ÀÖ½À´Ï´Ù. * Ãʱâ Ãâ·Â ÇÔ¼öÀÇ ¾Ë°í¸®Áòµµ ±×·¨½À´Ï´Ù. * n ^ x·Î ³ª´©¾î¼­ °ªÀ» _ltoa_sÇÔ¼ö¸¦ »ç¿ëÇÏ¿© * °¢ ÀÚ¸®¸¦ nÁø¹ýÀ¸·Î º¯È¯ Ãâ·ÂÇÏ´Â °ÍÀÔ´Ï´Ù. * ±Ùµ¥, ÀÌ ¹æ¹ýÀº È®½ÇÈ÷ ´À¸³´Ï´Ù. * °ö¼À, ³ª´°¼Àº¸´Ù´Â µ¡¼À, »¬¼ÀÀÌ ºü¸£¸ç * µ¡¼À »¬¼Àº¸´Ù´Â ºñÆ®, ½¬ÇÁÆ® ¿¬»êÀÌ ºü¸¨´Ï´Ù. * ¿©±â¼­ »ç¿ëÇÒ ¾Ë°í¸®Áò À̸§ÀÌ * shift and add 3 ¾Ë°í¸®Áò °°Àº¸»·Î double dabble ¾Ë°í¸®Áò(ÀÌÇÏ ´õºí´ëºí)ÀÔ´Ï´Ù. * À̸§¿¡¼­¿Í °°ÀÌ binary¸¦ bcd·Î ¹Ù²Ù´Âµ¥ ½¬ÇÁÆ®¿Í µ¡¼À¸¸À» ÀÌ¿ëÇϸç * ³ª´©¾î¼­ ³ª¸ÓÁö¸¦ ÃëÇÏ´Â ¹æ¹ý¿¡ ºñÇؼ­ È¿À²ÀûÀÎ ¾Ë°í¸®ÁòÀÔ´Ï´Ù. * * ¾Æ·¡ ¸µÅ©´Â À§Å°Çǵð¾Æ¿¡ ÀÖ´Â ´õºí´ëºí ¾Ë°í¸®Áò¿¡ ´ëÇÑ ¼³¸í±ÛÀ̸ç * http://en.wikipedia.org/wiki/Double_dabble * * ´ÙÀ½ÀÇ ¸µÅ©´Â Á¦ ºí·Î±×¿¡ À§ÀÇ ±ÛÀ» ¹ø¿ªÇغ» °ÍÀÔ´Ï´Ù. * http://transparenttape.tistory.com/entry/Double-DabbleShift-and-add-3-Algorithm * ´õºí´ëºí ¾Ë°í¸®ÁòÀ» Àß ¸ð¸£½Ã°Ú´Ù¸é Âü°íÇϽñ⠹ٶø´Ï´Ù. * * "Double Dabble algorithm in 32 bits" * radix_a¸¦ º¸¸é 32ºñÆ®¿¡´Â 10Áø¹ýÀ¸·Î´Â 9ÀÚ¸®¸¦ Ç¥Çö ÇÒ ¼ö ÀÖÀ½À» ¾Ë ¼ö ÀÖ½À´Ï´Ù. * ´õºí ´ëºí ¾Ë°í¸®ÁòÀ» ÀÌÇØ Çϼ̴ٸé, ¿©±âµµ ÀÌÇØ°¡ µÉ °ÍÀÔ´Ï´Ù. * 5ÀÌ»ó¿¡ 3À» ´õÇÏ´ø °ÍÀ» * 500000000(5¾ï)ÀÌ»ó¿¡ 1647483648À» ´õÇØÁÖ¸é µË´Ï´Ù. * 5¾ï ÀÌ»óÀÎ ¼ö¿¡ Àú ¼ýÀÚ¸¦ ´õÇÑ ÈÄ, ½¬ÇÁÆ®¸¦ ÇØÁÖ°Ô µÇ¸é 2^32ÀÌ»óÀÌ µÇ¾î * ÀÚ¸®¿Ã¸²ÀÌ ¹ß»ýÇÏ°Ô µË´Ï´Ù. * ¿ø¸®´Â µ¿ÀÏÇϸç, ¼ýÀÚ¸¸ ´Ù¸¦»ÓÀÔ´Ï´Ù. * * "Double Dabble algorithm in 32 bits for arbitrary radix" * ÀÌÁ¦ ´õºí´ëºí ¾Ë°í¸®ÁòÀ» ¼öÇÐÀûÀ¸·Î Á¢±ÙÇغ¸°Ú½À´Ï´Ù. * 5ÀÌ»óÀÎ ºí·°¿¡´Â 3À» ´õÇØÁÖ°í ½¬ÇÁÆ® ÇØÁشٰ¡ ÀÌ ¾Ë°í¸®ÁòÀÇ ÇÙ½ÉÀÔ´Ï´Ù. * * 5, 3À̶ó´Â ¼ýÀÚ°¡ ³ª¿Â ÀÌÀ¯¸¦ »ý°¢ÇØ º»´Ù¸é * 5 = º¯È¯ÇÏ°íÀÚ ÇÏ´Â Áø¹ýÀÇ ¹Ý ... (a) * 3 = ( (2 ^ ÀúÀåµÇ´Â ºí·°ÀÇ ÇÑºí·°ÀÇ ºñÆ® ¼ö) - º¯È¯ÇÏ°íÀÚ ÇÏ´Â Áø¹ý )/2 ... (b) * °ú °°Àº ½ÄÀ¸·Î ³ª¿Â°ÍÀÔ´Ï´Ù. * * 5 = 10 / 2 * 3 = (2^4 - 10) / 2 * * µû¶ó¼­ Àú ½Ä´ë·Î¶ó¸é ¾î´À Áø¹ý¿¡ ´ëÇؼ­µç ¾Ë°í¸®ÁòÀ» Àû¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. * ÇÏÁö¸¸, Ȧ¼ö Áø¹ý¿¡¼­´Â (a)½ÄÀ̳ª (b)½ÄÀ̳ª ¸ðµÎ 0.5°¡ »ý±é´Ï´Ù. * °á°úÀûÀ¸·Î´Â Ȧ¼ö Áø¹ýÀÏ ½Ã¿¡¼­´Â, (a)½ÄÀº ¿Ã¸², (b)½ÄÀº ³»¸² ó¸®ÇÕ´Ï´Ù. * ¿Ö ±×·¡¾ß ÇÏ´ÂÁö´Â ÇØ´ç ¾Ë°í¸®Áò ºÎºÐ¿¡¼­ ´Ù½Ã ¼³¸íÇÏ°Ú½À´Ï´Ù. * ¿©±â¼­ (b)½ÄÀÌ radix_c¸¦ ±¸ÇÑ ½ÄÀÔ´Ï´Ù. (a)½ÄÀº radix_b¸¦ ¿À¸¥ÂÊÀ¸·Î 1 ½¬ÇÁÆ® ÇÏ¸é µÇÁö¸¸ * (b)½ÄÀº Á¶±Ý º¹ÀâÇϱ⠶§¹®¿¡ ¹Ì¸® ±¸Çسù½À´Ï´Ù. * * ÀÌÁ¦ ÃÑ Á¤¸®ÀÔ´Ï´Ù. * Ãâ·ÂÀ» Çϴµ¥ À־ 2Áø¼ö °ªÀ» nÁø¹ýÀÇ x½Â ¹è¿­¿¡ º¯È¯ ÀúÀåÇÑ ÈÄ, * °¢ ¹è¿­¿¡ ÀúÀåµÇ¾î ÀÖ´Â °ªÀ» nÁø¹ýÀÇ x°³ÀÇ ¼ýÀÚ·Î ÂÉ°³´Â ½ÄÀ¸·Î Ãâ·ÂÀ» ÇÒ °ÍÀ̸ç * ¿©±â¼­ nÁø¹ýÀÇ x½Â ¹è¿­¿¡ ÀúÀåÇÏ´Â ¹æ¹ýÀº ´õºí´ëºí ¾Ë°í¸®ÁòÀ» * 32ºñÆ®¿¡ ÃÖÀûÈ­, ÀÓÀÇÀÇ Áø¹ý¿¡µµ Àû¿ëµÇµµ·Ï È®ÀåÇÏ¿© »ç¿ëÇÑ´Ù. * ¿©±â±îÁö°¡ ÃÑ Á¤¸®ÀÔ´Ï´Ù. * ÀÌÁ¦ radix_d¸¸ ³²¾Ò½À´Ï´Ù. * radix_d´Â nÁø¹ýÀÇ x½Â ¹è¿­ÀÇ Å©±â¸¦ ±¸ÇÏ´Â ½Ä¿¡¼­ºÎÅÍ µµÃâµÇ¾ú½À´Ï´Ù. * 2Áø¼ö·Î xÀÚ¸®ÀÎ ¼ö´Â 10Áø¼ö·Î´Â * x * log10(2) ÀÇ ¿Ã¸²°ª ÀÚ¸®¼ö¸¸Å­ÀÌ µË´Ï´Ù. * ÀÌ°ÍÀ» 32ºñÆ®¿¡ ¸ÂÃç »ý°¢Çغ¸¸é * 2Áø¼ö 32 * xÀÚ¸®ÀÎ ¼ö´Â 10Áø¼ö·Î * 32 * lgo10(2) * xÀÚ¸®°¡ µË´Ï´Ù. * ¿©±â¼­ ±¸ÇÏ°íÀÚ ÇÏ´Â °ÍÀº 10Áø¹ý ¹è¿­ÀÇ Å©±âÀ̹ǷΠ* Àú ¼ýÀÚ¸¦ 9·Î ³ª´©¾î ÁÝ´Ï´Ù. * ±×·¯¸é (32 * lgo10(2) * x) / 9°¡ µÇ¸ç * ÀÌ°ÍÀ» nÁø¹ýÀ¸·Î È®´ëÇÏ·Á¸é À§ ½Ä¿¡ log10(n)À» ³ª´©¾î ÁÖ¸é µË´Ï´Ù. * ±×·¡¼­ ´ÙÀ½°ú °°Àº ½ÄÀÌ ³ª¿À¸ç * ( ( 32 * log10(2) ) / ( log10(n) * radix_a[n]) ) * x * radix_d´Â ( 32 * log10(2) ) / ( log10(n) * radix_a[n])À» ±¸ÇÏ´Â ½ÄÀ̸ç * ³ª¿Â °ª¿¡ 10000À» °öÇÏ°í ¿Ã¸² ó¸® ÇÏ¿´½À´Ï´Ù. */ /* * 2^32 >= n ^ x (nÁø¹ýÀÇ x½Â) * À» ¸¸Á·ÇÏ´Â Á¦ÀÏ Å« x¸¦ * n¿¡ ´ëÇÏ¿© ¿À¸§Â÷¼øÀ¸·Î Á¤¸®ÇسõÀº°Í ÀÔ´Ï´Ù. */ const unsigned int radix_a[37] = { 0, 0, /* 2 */32, 20, 16, 13, 12,/* 6 */ /* 7 */11, 10, 10, 9, 9,/* 11 */ /* 12 */8, 8, 8, 8, 8,/* 16 */ /* 17 */7, 7, 7, 7, 7,/* 21 */ /* 22 */7, 7, 6, 6, 6,/* 26 */ /* 27 */6, 6, 6, 6, 6,/* 31 */ /* 32 */6, 6, 6, 6, 6 /* 36 */ }; /* * radix_a¸¦ ÀÌ¿ëÇØ ¹Ì¸® ±¸ÇسõÀº * 2^32 >= n ^ x (nÁø¹ýÀÇ x½Â) * À» ¸¸Á·ÇÏ´Â °¡Àå Å« n ^ x·Î * n ^ radix_a[n]À» ±¸ÇسõÀº °ÍÀÔ´Ï´Ù. */ const unsigned __int64 radix_b[37] = { 0, 0, /* 2 */ 4294967296, 3486784401, 4294967296, 1220703125, 2176782336,/* 6 */ /* 7 */ 1977326743, 1073741824, 3486784401, 1000000000, 2357947691,/* 11 */ /* 12 */ 429981696, 815730721, 1475789056, 2562890625, 4294967296,/* 16 */ /* 17 */ 410338673, 612220032, 893871739, 1280000000, 1801088541,/* 21 */ /* 22 */2494357888, 3404825447, 191102976, 244140625, 308915776,/* 26 */ /* 27 */ 387420489, 481890304, 594823321, 729000000, 887503681,/* 31 */ /* 32 */1073741824, 1291467969, 1544804416, 1838265625, 2176782336 /* 36 */ }; /* * radix_b¸¦ ÀÌ¿ëÇØ ¹Ì¸® ±¸ÇسõÀº * nÁø¹ýÀÇ * "(2^32 - radix_b[n])/2" * À» ±¸ÇÏ°í ³»¸² ÇÑ °ªÀÔ´Ï´Ù.(==¼Ò¼öÁ¡ ÀÌÇÏ ¹ö¸²) */ const unsigned long radix_c[37] = { 0, 0, /* 2 */ 0, 404091447, 0, 1537132085, 1059092480,/* 6 */ /* 7 */ 1158820276, 1610612736, 404091447, 1647483648, 968509802,/* 11 */ /* 12 */1932492800, 1739618287, 1409589120, 866038335, 0,/* 16 */ /* 17 */1942314311, 1841373632, 1700547778, 1507483648, 1246939377,/* 21 */ /* 22 */ 900304704, 445070924, 2051932160, 2025413335, 1993025760,/* 26 */ /* 27 */1953773403, 1906538496, 1850071987, 1782983648, 1703731807,/* 31 */ /* 32 */1610612736, 1501749663, 1375081440, 1228350835, 1059092480 /* 36 */ }; /* * radix_a¸¦ ÀÌ¿ëÇØ ¹Ì¸® ±¸ÇسõÀº * nÁø¹ýÀÇ * ( 32 * log10(2) ) / ( log10(n) * radix_a[n]) * À» ±¸ÇÑ ÈÄ, 10000À» °öÇÏ°í ¿Ã¸² ÇÑ °ªÀÔ´Ï´Ù.(==¼Ò¼öÁ¡ ÀÌÇÏ ¿Ã¸²) */ const unsigned int radix_d[37] = { 0, 0, /* 2 */ 10000, 10095, 10000, 10602, 10317,/* 6 */ /* 7 */ 10363, 10667, 10095, 10704, 10278,/* 11 */ /* 12 */11158, 10810, 10506, 10239, 10000,/* 16 */ /* 17 */11185, 10963, 10762, 10578, 10408,/* 21 */ /* 22 */10252, 10106, 11633, 11485, 11347,/* 26 */ /* 27 */11217, 11095, 10979, 10870, 10766,/* 31 */ /* 32 */10667, 10573, 10484, 10398, 10317 /* 36 */ }; } void BigInteger::Allocate(length c) { len = c; blk = new blocktype[len]; } void BigInteger::Reallocate(length c) { if (len != c) { if (blk != NULL) delete [] blk; Allocate(c); } } void BigInteger::Blkinit() { memset(blk, 0, len << 2); } void BigInteger::Blkcopy(const BigInteger &x) { memcpy(blk, x.blk, x.len << 2); } void BigInteger::SetZero() { len = 0; blk = NULL; sign = Zero; } void BigInteger::Reset() { if (blk != NULL) delete [] blk; SetZero(); } void BigInteger::ZapLeadingZeros() { while(len > 0 && blk[len-1] == 0) len--; } BigInteger::BigInteger() { SetZero(); } BigInteger::~BigInteger() { if (blk != NULL) delete [] blk; } BigInteger::BigInteger(const BigInteger &x) { if (x.sign == Zero) SetZero(); else { Allocate(x.len); Blkcopy(x); sign = x.sign; } } BigInteger & BigInteger::operator =(const BigInteger &x) { if (this != &x) { if (x.sign == Zero) SetZero(); else { Reallocate(x.len); Blkcopy(x); sign = x.sign; } } return *this; } BigInteger::BigInteger( bool x) { if (x == true) { Allocate(1); blk[0] = 1; sign = Positive; } else SetZero(); } BigInteger::BigInteger(unsigned char x) { ConversionAssist1 (x); } BigInteger::BigInteger( char x) { ConversionAssist2 (x); } BigInteger::BigInteger(unsigned short x) { ConversionAssist1(x); } BigInteger::BigInteger( short x) { ConversionAssist2 (x); } BigInteger::BigInteger(unsigned long x) { ConversionAssist1 (x); } BigInteger::BigInteger( long x) { ConversionAssist2 (x); } BigInteger::BigInteger(unsigned int x) { if (sizeof(x) == 4) ConversionAssist1 (x); else ConversionAssist1(x); } BigInteger::BigInteger( int x) { if (sizeof(x) == 4) ConversionAssist2 (x); else ConversionAssist2(x); } BigInteger::BigInteger(unsigned long long x) { ConversionAssist1(x);} BigInteger::BigInteger( long long x) { ConversionAssist2(x);} BigInteger::operator bool () const { if (sign == Zero) return false; return true; } BigInteger::operator unsigned char () const {return ConversionAssist3 ();} BigInteger::operator char () const {return ConversionAssist4 ();} BigInteger::operator unsigned short () const {return ConversionAssist3 ();} BigInteger::operator short () const {return ConversionAssist4 ();} BigInteger::operator unsigned long () const {return ConversionAssist3 ();} BigInteger::operator long () const {return ConversionAssist4 ();} BigInteger::operator unsigned int () const {return ConversionAssist3 ();} BigInteger::operator int () const {return ConversionAssist4 ();} BigInteger::operator unsigned long long() const { unsigned __int64 x = 0; if (sign == Zero) return x; else if (sign == Negative) { #if defined(_DEBUG) throw "À½¼ö¸¦ Unsigned·Î ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù."; #else return x; #endif } else if (len <= 2) { x = blk[0]; if (len == 1) return x; x += unsigned __int64(blk[1]) << N; return x; } #if defined(_DEBUG) throw "°ªÀÌ ³Ê¹« Ä¿¼­ º¯È¯ ÇÒ ¼ö ¾ø½À´Ï´Ù."; #else return x; #endif } BigInteger::operator long long() const { __int64 x = 0; if (sign == Zero) return x; else if (len <= 2) { x = blk[0]; if (len == 2 && !(blk[1] >> 31) ) x += __int64(blk[1]) << N; } #if defined(_DEBUG) else { throw "°ªÀÌ ³Ê¹« Ä¿¼­ º¯È¯ ÇÒ ¼ö ¾ø½À´Ï´Ù."; } #endif return (sign == Positive) ? x : -x; } void BigInteger::DoubleDabble(BigInteger &dest, int radix) const { if ( !( radix >=2 && radix <=36 ) ) { #if defined(_DEBUG) throw "2 ~ 36Áø¹ý±îÁö¸¸ °¡´ÉÇÕ´Ï´Ù."; #else return; #endif } // 0Àº ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÑ ÇÔ¼ö¿¡¼­ ¸ÕÀú ó¸®ÇÕ´Ï´Ù. // 0ÀÇ Á¤ÀǶ§¹®¿¡, ÇÒ´çµÇÁö ¾ÊÀº ÁÖ¼Ò¸¦ Á¢±ÙÇÏ°Ô µÇ¾î ¿¡·¯°¡ ³³´Ï´Ù. // µû¶ó¼­, ¾ÖÃÊ¿¡ Áø¹ý¿¡ »ó°ü¾øÀÌ 0¿¡ ´ëÇؼ­´Â Ãâ·ÂÀ» ÇÏ°Ô ÇÏ¿´°í, // ¿©±â¼­´Â 0¿¡ ´ëÇؼ­´Â ½Å°æ ¾²Áö ¾Ê°Ô ÇÏ¿´½À´Ï´Ù. // ÀÌ ¾Ë°í¸®ÁòÀ» ±ÍÇÏÀÇ ÇÁ·Î±×·¥¿¡ Àû¿ëÇÒ °èȹÀ̶ó¸é // ¿©±â¿¡ 0¿¡ ´ëÇÑ Ã³¸®¸¦ ÇÒ ÇÊ¿ä°¡ ÀÖÀ» ¼öµµ ÀÖ½À´Ï´Ù. // ÀÌÁ¦ this´Â ¾ç¼ö ¾Æ´Ï¸é À½¼öÀÔ´Ï´Ù. // Ãâ·ÂÇÏ°íÀÚ ÇÏ´Â Áø¹ýÀÌ È¦¼ö¶ó¸é // DD_OddÇÔ¼ö·Î º¸³À´Ï´Ù. // radix°¡ Ȧ¼öÀÏ ¶§, // ¦¼öÀÏ ¶§¿¡ ºñÇؼ­, Ãß°¡ÀûÀ¸·Î ó¸®ÇØ¾ß ÇÒ°ÍÀÌ ³Ê¹« ¸¹¾Æ¼­ // ¾Æ¿¹ ¦¼ö¿Í Ȧ¼öÀÏ ¶§¸¦ ºÐ¸®ÇÏ¿´½À´Ï´Ù. if (radix & 1) { DD_Odd(dest, radix); return; } // dest°¡ µÉ ¼ö ÀÖ´Â ÃÖ´ë ±æÀ̸¦ ±¸ÇÕ´Ï´Ù. length maxlen = length(unsigned __int64(len)*radix_d[radix]/10000 + 1); dest.Reallocate(maxlen); dest.Blkinit(); dest.len = 1; // Ãʱâ destÀÇ ±æÀ̸¦ 1·Î ¼³Á¤ÇÕ´Ï´Ù. dest.sign = sign; index i, j; length bit; blocktype bound = blocktype(radix_b[radix]>>1); i = len; while (i--) // thisÀÇ ³ôÀº ÀÚ¸®ÀÇ blkºÎÅÍ { bit = N; while (bit--) // blkÀÇ ³ôÀº ÀÚ¸®ºÎÅÍ { // destÀÇ ¸ðµç blk¸¦ °Ë»çÇÏ¿© // boundÀÌ»óÀÎ ºí·°À» ã¾Æ ´õÇØÁÝ´Ï´Ù. j = dest.len; while (j--) { if (dest.blk[j] >= bound) dest.blk[j] += radix_c[radix]; } // destÀÇ ±æÀ̸¦ Çϳª ´Ã·ÁÁÝ´Ï´Ù. if (dest.blk[dest.len - 1] & 0x80000000) ++dest.len; // destÀÇ ¸ðµç ºí·°À» ¿ÞÂÊÀ¸·Î 1 ½¬ÇÁÆ®ÇÕ´Ï´Ù. j = dest.len; while (j--) { dest.blk[j] <<= 1; if (j != 0 && dest.blk[j - 1] & 0x80000000) dest.blk[j] |= 1; } // this¿¡¼­ dest·Î 1ºñÆ® º¹»çÇÕ´Ï´Ù. if(blk[i] & (1ul<> 1) + 1; blocktype **isadd; isadd = (blocktype**)malloc(maxlen << 2); i = len; while (i--) // thisÀÇ ³ôÀº ÀÚ¸®ÀÇ blkºÎÅÍ { bit = N; while (bit--) // blkÀÇ ³ôÀº ÀÚ¸®ºÎÅÍ { // destÀÇ ¸ðµç blk¸¦ °Ë»çÇÏ¿© // boundÀÌ»óÀÎ ºí·°À» ã¾Æ ´õÇØÁÝ´Ï´Ù. j = dest.len; k = 0; while (j--) { if (dest.blk[j] >= bound) { dest.blk[j] += radix_c[radix]; isadd[k++] = &dest.blk[j]; } } // destÀÇ ±æÀ̸¦ Çϳª ´Ã·ÁÁÝ´Ï´Ù. if (dest.blk[dest.len - 1] & 0x80000000) ++dest.len; // destÀÇ ¸ðµç ºí·°À» ¿ÞÂÊÀ¸·Î 1 ½¬ÇÁÆ®ÇÕ´Ï´Ù. j = dest.len; while (j--) { dest.blk[j] <<= 1; if (j != 0 && dest.blk[j - 1] & 0x80000000) dest.blk[j] |= 1; } // this¿¡¼­ dest·Î 1ºñÆ® º¹»çÇÕ´Ï´Ù. if(blk[i] & (1ul<= rb) { dest.blk[j] -= rb; for (k = j + 1; ; ++k) { if (++dest.blk[k] != 0) break; } } } if (j != maxlen && dest.blk[j] != 0) ++dest.len; } } free(isadd); } BigInteger::BigInteger(const char *str, int radix/* =10 */) { SetZero(); std::string temp(str); stob(temp, radix); } BigInteger::BigInteger(const std::string &str, int radix/* =10 */) { SetZero(); stob(str, radix); } const BigInteger & BigInteger::stob(const std::string &str, int radix/* =10 */) { // 2~36Áø¹ý ¸ðµÎ·Î ÀÔ·Â ÇÒ ¼ö ÀÖ½À´Ï´Ù. // ´Ü, ÀԷ¿¡¼­ ¹ß»ýÇÒ ¼ö ÀÖ´Â ½Ç¼ö´Â Á¡°ËÇÏÁö ¾Ê½À´Ï´Ù! // ¿¹·Î.. 1234a324aa32432a¸¦ 10Áø¹ýÀ¸·Î ÀÔ·Â ÇÑ´Ù¸é // atoi ÇÔ¼ö¿¡¼­´Â 1234°¡ µÇÁö¸¸ ¿©±â¼­´Â 4°¡ µË´Ï´Ù. if ( !( radix >=2 && radix <=36 ) ) { #if defined(_DEBUG) throw "2 ~ 36Áø¹ý±îÁö¸¸ °¡´ÉÇÕ´Ï´Ù."; #else return *this; #endif } // *this¸¦ 0À¸·Î ÃʱâÈ­ ÇÕ´Ï´Ù. // 0À¸·Î ÃʱâÈ­ ÇÏÁö ¾ÊÀ¸¸é const char * // const string & »ý¼ºÀÚ¿¡¼­ ¿À·ù°¡ ³ª¸ç // ÀÌ ÇÔ¼ö¸¦ µû·Î »ç¿ë½Ã¿¡µµ Á¤È®ÇÑ °ªÀÌ ³ª¿ÀÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. /*Allocate(1); blk[0] = 0; sign = Zero;*/ Reset(); if (str.size() == 1 && str[0] == '0') return *this; // ¹®ÀÚ¿­À» ¸î°³¾¿ ²÷¾î¼­ ÀÐÀ»Áö Á¤ÇÕ´Ï´Ù. length read_length = radix_a[radix]; // ÀÔ·ÂÀº Ãâ·ÂÀ» ¿ªÀ¸·Î »ý°¢ÇÏ¸é µË´Ï´Ù. // ³·ÀºÀÚ¸®ºÎÅÍ read_length¾¿ ²÷¾î ÀÐÀº°Í¿¡ // base¸¦ j¹ø °öÇؼ­ Â÷·ÊÂ÷·Ê °á°ú°ª¿¡ ´õÇÏ¸é µË´Ï´Ù. BigInteger base(radix_b[radix]); // ¹®ÀÚ¿­ÀÇ ±æÀ̸¦ ±¸ÇÕ´Ï´Ù. unsigned long offset = str.size(); // ¹ØÀÇ _Copy_s ÇÔ¼ö°¡ ÇÊ¿ä·Î ÇÕ´Ï´Ù. // Á¤È®ÇÑ À§Ä¡¿Í °¹¼ö¸¦ Àμö·Î ³Ö¾î¾ß // Á¤È®ÇÏ°í ¿À·ù¾øÀÌ ÀÛµ¿ÇÕ´Ï´Ù. length blocklen = offset / read_length; unsigned long rest = offset % read_length; // read_length¸¸Å­ ÀÐÀº°ÍÀ» Àá½Ã ÀúÀåÇÕ´Ï´Ù. char temp[33] = {0,}; // ¹®ÀÚ¿­¿¡ Áø¹ýÀÌ»óÀÇ ¼ýÀÚ, ¹®ÀÚ°¡ ÀÖ´ÂÁö Á¡°ËÇϱâ À§Çؼ­ »ç¿ëÇÕ´Ï´Ù. char *error_ptr; BigInteger x; // ¹®ÀÚ¿­ ¸Ç ¾Õ¿¡ ºÎÈ£°¡ ÀÖÀ» ¼ö ÀÖ½À´Ï´Ù. // ºÎÈ£°¡ ÀÖÀ» °æ¿ì¸¦ ó¸®ÇØ ÁÝ´Ï´Ù. unsigned long signexist = 0; if (str[0] == '+') { if (str.size() == 2 && str[1] == '0') return _Zero; // + ºÎÈ£°¡ ÀÖ´Ù°í Çؼ­ sign¸¦ ´ëÀÔ¹ÞÁö ¾Ê½À´Ï´Ù. signexist = 1; } else if (str[0] == '-') { // "-0"°ú °°Àº °æ¿ìÀÔ´Ï´Ù. if (str.size() == 2 && str[1] == '0') return _Zero; // ±× ¹Û¿¡ À½¼ö¸é ºÎÈ£¸¦ ´ëÀÔÇÕ´Ï´Ù. signexist = 1; sign = Negative; } if (sign != Negative) sign = Positive; unsigned long i, j; i = 0; j = 0; // read_length¾¿ ¿ÏÀüÇÏ°Ô ²÷¾î ÀÐÀ» ¼ö ÀÖ´Â °æ¿ì // while¹®¾ÈÀ¸·Î µé¾î°¡°Ô µË´Ï´Ù. while (blocklen--) { // offsetÀ» ¹®ÀÚ¿­ÀÇ ¸Ç ³¡¿¡¼­ // read_length¸¸Å­ »©ÁÝ´Ï´Ù. offset -= read_length; // offset¿¡¼­ read_length¸¸Å­ Àо temp¿¡ ÀúÀå str._Copy_s(temp, 33, read_length, offset); // strtoulÇÔ¼ö´Â Áø¹ýÀ¸·Î µÇÀÖ´Â ¹®ÀÚ¿­À» // unsigned longÇüÀ¸·Î ¹Ù²ãÁÝ´Ï´Ù. // ´ëÀÔ ¿¬»êÀÚ·Î x¿¡ Àß ´ëÀԵ˴ϴÙ. x = strtoul(temp, &error_ptr, radix); // x¿¡ base¸¦ j¹ø °öÇÕ´Ï´Ù. // ÀÚ¸®¼ö¸¦ »ý°¢ÇؾßÇϱ⠶§¹®ÀÔ´Ï´Ù. while (j--) x *= base; add(*this, x); j = ++i; // ¹®ÀÚ¿­¿¡ Áø¹ý ÀÌ»óÀÇ ¼ýÀÚ,¹®ÀÚ°¡ ÀÖÀ¸¸é // goto·Î ÇÔ¼ö¸¦ Á¾·á½Ãŵ´Ï´Ù. // throw¸¦ ´øÁöÁö ¾Ê½À´Ï´Ù. if (*error_ptr != 0) return *this; } // read_length¿¡ ºÎÁ·ÇÏ°Ô ²÷¾î ÀÐÀ» ¼ö ÀÖ´Â °æ¿ì if (rest != 0) { memset(temp, 0, 33); offset -= (rest - signexist); if (signexist == 1) rest--; str._Copy_s(temp, 33, rest, offset); x = strtoul(temp, &error_ptr, radix); if (j != 0) { while (j--) x *= base; } add(*this, x); } return *this; } const std::string BigInteger::btos(int radix) const { std::string str; // ¸®ÅϵǴ °ªÀÔ´Ï´Ù. if ( !( radix >=2 && radix <=36 ) ) { #if defined(_DEBUG) throw "2 ~ 36Áø¹ý±îÁö¸¸ °¡´ÉÇÕ´Ï´Ù."; #else return str; #endif } BigInteger dest; str.reserve( dest.len * radix_a[radix] ); // 0 ó¸® if (sign == Zero) { str += '0'; return str; } DoubleDabble(dest, radix); if (dest.sign == Negative) str += '-'; char prM[33]; length i = dest.len - 1; _ltoa_s(dest.blk[i], prM, radix); // Á¦ÀÏ ³ôÀº ÀÚ¸® ó¸® str += prM; // ±× ÀÌÇÏ´Â 00001°ú °°ÀÌ ¾Õ¿¡ 0ÀÌ ÀÖÀ» ¼öµµ Àֱ⠶§¹®¿¡ // 0ÀÌ ÀÖ¾î¾ß ÇÑ´Ù¸é 0À» Ãß°¡ÇÑ ÈÄ, ¼ö¸¦ ´ëÀÔÇÏ´Â ¹æ½ÄÀ¸·Î ó¸®ÇØ¾ß ÇÕ´Ï´Ù. unsigned long j; while (i) { --i; memset(prM, 0, 33); _ltoa_s(dest.blk[i], prM, radix); // ¼±µÎ 0À» ´ëÀÔ j = strlen(prM); if (j != radix_a[radix]) while (j != radix_a[radix]) { str += '0'; j++; } // 0 ´ëÀÔ ÈÄ, str¿¡ prMÀ» ´ëÀÔ str += prM; } return str; } std::ostream & operator <<(std::ostream &os, const BigInteger &x) { int base; long osFlags = os.flags(); if (x.sign == BigInteger::Negative) os << '-'; else if (x.sign == BigInteger::Positive && os.flags() & os.showpos) os << '+'; if (osFlags & os.dec) base = 10; else if (osFlags & os.hex) { base = 16; if (osFlags & os.showbase) os << "0x"; } else if (osFlags & os.oct) { base = 8; if (osFlags & os.showbase) os << '0'; } if (x.sign == BigInteger::Zero) { os << '0'; return os; } BigInteger dst; BigInteger *pB = (BigInteger *)&x; os << std::setfill('0'); if (base == 10) { x.DoubleDabble(dst, base); os << dst.blk[dst.len - 1]; for (int i = dst.len - 2; i >= 0; --i) os << std::setw(9) << dst.blk[i]; } else if (base == 8) { x.DoubleDabble(dst, base); pB = &dst; } if (base != 10) { char prM[11] = {0, }; _ltoa_s(pB->blk[pB->len - 1], prM, base); os << prM; for (int i = pB->len - 2; i >= 0; --i) { memset(prM, 0, 11); _ltoa_s(pB->blk[i], prM, base); os << std::setw(radix_a[base]) << prM; } } os << std::setfill(' '); return os; } void BigInteger::print(int radix/* =10 */) const { if ( !( radix >=2 && radix <=36 ) ) { #if defined(_DEBUG) throw "2 ~ 36Áø¹ý±îÁö¸¸ °¡´ÉÇÕ´Ï´Ù."; #else return; #endif } if (sign == BigInteger::Zero) { std::cout << '0'; return; } else if (sign == BigInteger::Negative) { std::cout << '-'; } BigInteger temp; BigInteger *pB = (BigInteger *)this; char prM[33] = {0, }; if (radix != 2 && radix != 4 && radix != 16) { DoubleDabble(temp, radix); pB = &temp; } index i = pB->len - 1; std::cout << std::setfill('0'); if (radix == 10) { std::cout << pB->blk[i]; while (i--) std::cout << std::setw(radix_a[radix]) << pB->blk[i]; } else { _ltoa_s(pB->blk[i], prM, radix); std::cout << prM; while (i--) { memset(prM, 0, 33); _ltoa_s(pB->blk[i], prM, radix); std::cout << std::setw(radix_a[radix]) << prM; } } std::cout << std::setfill(' '); } std::istream & operator >>(std::istream &is, BigInteger &x) { std::string str; is >> str; x.stob(str); return is; } const int BigInteger::compare(const BigInteger &x) const { if (this == &x) return 0; if (len < x.len) return -1; else if (len > x.len) return 1; else { // ÇÑºí·°¾¿ ³ôÀºÀÚ¸®ºÎÅÍ ºñ±³ÇÕ´Ï´Ù. length i = len; while (i > 0) { i--; if (blk[i] == x.blk[i]) continue; else if (blk[i] > x.blk[i]) return 1; else return -1; } // ¸ðµç ºí·°ÀÌ °°Àº °æ¿ìÀ̹ǷÎ, Å©±â°¡ °°½À´Ï´Ù. return 0; } } const BigInteger::_sign BigInteger::getsign() const { return sign; }; bool BigInteger::operator ==(const BigInteger &x) const { if (this == &x) return true; if (sign != x.sign) return false; if (len != x.len) return false; length i = len; while (i > 0) { i--; if (blk[i] != x.blk[i]) return false; } return true; } bool BigInteger::operator !=(const BigInteger &x) const { return !( operator ==(x) ); } bool BigInteger::operator > (const BigInteger &x) const { if (this == &x) return false; if (sign > x.sign) return true; else if (sign < x.sign) return false; else { // ºÎÈ£¿¡ µû¶ó ¸®ÅÏ°ªÀÌ ´Þ¶óÁý´Ï´Ù. if (len > x.len) if (sign == Positive) return true; else return false; else if (len < x.len) if (sign == Positive) return false; else return true; else { length i = len; while (i > 0) { i--; if (blk[i] == x.blk[i]) continue; else if (blk[i] > x.blk[i]) if (sign == Positive) return true; else return false; else if (sign == Positive) return false; else return true; } return false; // µÎ ¼ö°¡ °°Àº °æ¿ìÀ̹ǷΠ} } } bool BigInteger::operator >=(const BigInteger &x) const { if (this == &x) return true; if (sign > x.sign) return true; else if (sign < x.sign) return false; else { if (len > x.len) if (sign == Positive) return true; else return false; else if (len < x.len) if (sign == Positive) return false; else return true; else { length i = len; while (i > 0) { i--; if (blk[i] == x.blk[i]) continue; else if (blk[i] > x.blk[i]) return true; else return false; } return true; // µÎ ¼ö°¡ °°Àº °æ¿ì } } } bool BigInteger::operator < (const BigInteger &x) const { return !( operator >=(x) ); } bool BigInteger::operator <=(const BigInteger &x) const { return !( operator >(x) ); } unsigned __int64 BigInteger::bitlength() const { if (sign == Zero) return 0; blocktype LeftMostBlock = blk[len - 1]; unsigned __int64 LeftMostBlockLen = 0; while (LeftMostBlock != 0) { LeftMostBlock >>= 1; LeftMostBlockLen++; } return LeftMostBlockLen + unsigned __int64( (len - 1) ) * N; } BigInteger::length BigInteger::blklength() const { return len; } const BigInteger BigInteger::operator &(const BigInteger &x) const { if (this == &x) return *this; BigInteger temp; // µÑ Áß Çϳª°¡ 0À̶ó¸é ¿¬»ê°ªÀº 0ÀÔ´Ï´Ù. if (sign == Zero || x.sign == Zero) return temp; // tempÀÇ ±æÀÌ´Â µÑ Áß ÂªÀº°ÍÀ¸·Î ÀçÇÒ´çÇÕ´Ï´Ù. temp.Allocate( (len < x.len) ? len : x.len ); index i; for (i = 0; i < temp.len; i++) temp.blk[i] = blk[i] & x.blk[i]; temp.sign = (sign == Positive || x.sign == Positive) ? Positive : Negative; // ¼±µÎ 0 ºí·°À» Á¦°Å ÇÕ´Ï´Ù. temp.ZapLeadingZeros(); // this¿Í xÀÇ ºñÆ®ÀÇ ±³ÁýÇÕÀÌ Çϳªµµ ¾øÀ¸¸é... // temp´Â 0ÀÔ´Ï´Ù. if (temp.len == 0) temp.sign = Zero; return temp; } const BigInteger & BigInteger::operator &=(const BigInteger &x) { return *this = *this & x; } const BigInteger BigInteger::operator |(const BigInteger &x) const { if (this == &x) return *this; BigInteger temp; // µÑ ´Ù 0ÀÎ °æ¿ì if (sign == Zero && x.sign == Zero) return temp; // this¸¸ 0ÀÎ °æ¿ì else if (sign == Zero) return x; // x¸¸ 0ÀÎ °æ¿ì else if (x.sign == Zero) return *this; const BigInteger *pLeft, *pRight; if (len >= x.len) { pLeft = this; pRight = &x; } else { pLeft = &x; pRight = this; } temp.Allocate(pLeft->len); index i; for (i =0; i < pRight->len; i++) temp.blk[i] = pLeft->blk[i] | pRight->blk[i]; for (; i < pLeft->len; i++) temp.blk[i] = pLeft->blk[i]; temp.sign = (pLeft->sign == Negative || pRight->sign == Negative) ? Negative : Positive; // ¿¬»ê °á°ú·Î 0ÀÌ ³ª¿Ã ¼ö ¾ø½À´Ï´Ù./ return temp; } const BigInteger & BigInteger::operator |=(const BigInteger &x) { return *this = *this | x; } const BigInteger BigInteger::operator ^(const BigInteger &x) const { BigInteger temp; if (this == &x) return temp; // µÑ ´Ù 0ÀÎ °æ¿ì if (sign == Zero && x.sign == Zero) return temp; // this¸¸ 0ÀÎ °æ¿ì else if (sign == Zero) return x; // x¸¸ 0ÀÎ °æ¿ì else if (x.sign == Zero) return *this; const BigInteger *pLeft, *pRight; if (len >= x.len) { pLeft = this; pRight = &x; } else { pLeft = &x; pRight = this; } temp.Allocate(pLeft->len); index i; for (i =0; i < pRight->len; i++) temp.blk[i] = pLeft->blk[i] ^ pRight->blk[i]; for (; i < pLeft->len; i++) temp.blk[i] = pLeft->blk[i]; temp.sign = (sign == x.sign) ? Positive : Negative; temp.ZapLeadingZeros(); // ¿¬»ê °á°ú·Î 0ÀÌ ³ª¿Ã ¼ö ÀÖ½À´Ï´Ù. if (temp.len == 0) temp.sign = Zero; return temp; } const BigInteger & BigInteger::operator ^=(const BigInteger &x) { return *this = *this ^ x; } const BigInteger BigInteger::operator ~() const { BigInteger temp(*this); if (sign == Positive) temp.sign = Negative; else if (sign == Negative) temp.sign = Positive; temp -= _One; return temp; } const BigInteger::blocktype BigInteger::Get_LShiftedBlock(index x, length n) const { // x´Â 0~len±îÁöÀÇ ¹üÀ§¸¦ °¡Áý´Ï´Ù. // nÀº 0~31±îÁöÀÇ ¹üÀ§¸¦ °¡Áý´Ï´Ù. // x Àü ºí·ÏÀÇ »óÀ§ nºñÆ®¸¦ ÃßÃâ ÇÕ´Ï´Ù. blocktype lowblk = (x == 0 || n == 0) ? 0 : ( blk[x - 1] >> (N - n) ); // x ºí·ÏÀ» ¿ÞÂÊÀ¸·Î n¹ø ½¬ÇÁÆ®ÇÕ´Ï´Ù. blocktype highblk = (x == len) ? 0 :( blk[x] << n ); // À§ µÎ ºí·°ÀÇ ÇÕÁýÇÕÀ» ¸®ÅÏÇÕ´Ï´Ù. return lowblk | highblk; } const BigInteger BigInteger::operator <<(int leftmove) const { // (*this) * 2^(leftmove)¸¦ ¿¬»ê BigInteger temp; // °á°ú°ª ¸®ÅÏ¿ë /* * Ư¼ö °æ¿ì¸¦ Á¦¿ÜÇÕ´Ï´Ù. * 1. *this°¡ 0À̸é, 0 ¸®ÅÏ * 2. leftmove°¡ 0À̸é, *this ¸®ÅÏ * 3. leftmove°¡ À½¼ö¸é, >> ½¬ÇÁÆ®·Î ¿¬»ê */ if (sign == Zero) return temp; if (leftmove == 0) return *this; else if (leftmove < 0) return *this >> (-leftmove); length shiftblocks = leftmove / N; length shiftbits = leftmove % N; // +1Àº shitfbits¶§¹®¿¡ »ý±â´Â Ãß°¡µÇ´Â ºí·Ï ÀúÀå¿ë temp.Allocate(len + shiftblocks + 1); temp.Blkinit(); // ÇÑºí·°¾¿ shiftbits¸¸Å­ ½¬ÇÁÆ® ½ÃÄÑ ´ëÀÔÇØÁÝ´Ï´Ù. index i, j; for (i = 0, j = shiftblocks; i <= len; i++, j++) temp.blk[j] = Get_LShiftedBlock(i, shiftbits); // Get_LShiftedBlock(len - 1, shiftbits)°¡ 0ÀÏ °æ¿ì... if (temp.blk[temp.len - 1] == 0) temp.len--; temp.sign = sign; return temp; } const BigInteger & BigInteger::operator <<=(int leftmove) { return *this = *this << leftmove; } const BigInteger BigInteger::operator >>(int rightmove) const { BigInteger temp; if (sign == Zero) return temp; if (rightmove == 0) return *this; else if (rightmove < 0) return *this << (-rightmove); // °á°ú°ªÀÌ 0ÀÌ ³ª¿À´Â °æ¿ì if (unsigned __int64(rightmove) >= bitlength()) return temp; length rightShiftBlocks = (rightmove + N - 1) / N; length leftShiftBits = N * rightShiftBlocks - rightmove; // ÀÌÁ¦ (N * rightShiftBlocks - leftShiftBits) == rightmove // ±×¸®°í 0 <= leftShiftBits < N °¡ ¼º¸³ÇÕ´Ï´Ù. // + 1: ÃÖ»óÀ§ ºí·° ¶§¹®ÀÔ´Ï´Ù. temp.Allocate(len + 1 - rightShiftBlocks); index i, j; for (j = rightShiftBlocks, i = 0; j <= len; j++, i++) temp.blk[i] = Get_LShiftedBlock(j, leftShiftBits); if (temp.blk[temp.len - 1] == 0) temp.len--; // À§¿¡¼­ °á°ú°ªÀÌ 0ÀÌ ³ª¿À´Â °ÍÀ» Á¦°Å ÇÏ¿´±â ¶§¹®¿¡ // ±×´ë·Î ºÎÈ£¸¦ ³Ö´Â´Ù. temp.sign = sign; return temp; } const BigInteger & BigInteger::operator >>=(int rightmove) { return *this = *this >> rightmove; } void BigInteger::add(const BigInteger &Left, const BigInteger &Right) { // Left¿Í RightÀÇ Å©±â¸¦ ´õÇÏ¿© this¿¡ ÀúÀåÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. // stob ÇÔ¼ö¿¡¼­ // this->add(*this, x)¿Í °°ÀÌ È£ÃâÇϱ⠶§¹®¿¡ if (this == &Left) { BigInteger Left_temp(Left); add(Left_temp, Right); return; } // È£Ãâ ÇÔ¼öºÎºÐÀ» °£·«ÇÏ°Ô Çϱâ À§Çؼ­ if (Left.len < Right.len) { add(Right, Left); return; } // ÀÌÁ¦, Left¿Í RightÀÇ ±æÀÌ°£¿¡´Â // Left.len >= Right.len ÀÌ ¼º¸³ Reallocate(Left.len + 1); blocktype blk_temp = 0; // µÎ ºí·°ÀÇ ÇÕÀ» Àá½Ã ÀúÀåÇϱâ À§ÇØ // ÀÚ¸®¿Ã¸² 󸮿ë // carryIn : ÀÌÀü ÀÚ¸®¿¡¼­ ÀÚ¸®¿Ã¸² ¹ß»ý? // carryOut : Çö ÀÚ¸®¿¡¼­ ¿¬»êÀ¸·Î ÀÚ¸®¿Ã¸² ¹ß»ý? bool carryIn, carryOut; index i; // ³·Àº ÀÚ¸® ¸¸Å­ ·çÇÁ¸¦ µ¹¸ç µ¡¼À ¿¬»ê for(i = 0, carryIn = false; i < Right.len; i++){ blk_temp = Left.blk[i] + Right.blk[i]; // ÀÚ¸® ¿Ã¸²ÀÌ ¹ß»ýÇϸé // blk_temp < Left.blk[i] // blk_temp < Right.blk[i] // À§ µÎ°³¸¦ ¸ðµÎ ¸¸Á·ÇÑ´Ù. // ±×·¡¼­ µÎ °³Áß¿¡ Çϳª¸¸ »ç¿ëÇÏ¿© ºñ±³ÇØ ÁÖ¸éµÈ´Ù. carryOut = (blk_temp < Left.blk[i]); if (carryIn) { // Àü ÀÚ¸®¿¡¼­ ÀÚ¸®¿Ã¸² ¹ß»ýÇߴ°¡? ++blk_temp; // CarryInÀ¸·Î ÀÎÇÑ ÀÚ¸®¿Ã¸² ¹ß»ý °¡´É¼º ó¸® carryOut |= (blk_temp==0); } blk[i] = blk_temp; carryIn = carryOut; } // blk[Right.len - 1]¿¡¼­ ÀÚ¸®¿Ã¸² ¹ß»ýÇߴ°¡? // ¶ÇÇÑ, Å« °¡´É¼ºÀº ¾øÁö¸¸ ¿¬¼â ÀÚ¸®¿Ã¸²ÀÌ °¡´ÉÇÏ´Ù // ex) 799 + 1°ú °°Àº °æ¿ì¿Í ºñ½ÁÇÑ ¸Æ¶ô for(; carryIn && i < Left.len; i++){ blk[i] = Left.blk[i] + 1; carryIn = (blk[i] == 0); } // ³ª¸ÓÁö´Â ±×´ë·Î ´ëÀÔ for(; i < Left.len; i++){ blk[i] = Left.blk[i]; } // ¿¬¼â ÀÚ¸®¿Ã¸²ÀÌ ³¡±îÁö ÀϾ °æ¿ìÀÌ´Ù. // À§¿¡¼­ 799 + 1ÀÌ ¾Æ´Ñ 999 + 1°ú °°Àº °æ¿ì´Ù. // ¿¬»ê°ªÀÌ ÀÚ¸´¼ö°¡ 1 Áõ°¡Çϸç Áõ°¡ÇÑ ÀÚ¸®ÀÇ ¼ýÀÚ´Â 1ÀÌ´Ù. // ¾Æ´Ï¶ó¸é len 1 °¨¼Ò if(carryIn) blk[i]=1; else len--; } void BigInteger::subtract (const BigInteger &Left, const BigInteger &Right) { // LeftÀÇ Å©±â¿¡¼­ RightÀÇ Å©±â¸¸Å­À» »©¼­ this¿¡ ÀúÀåÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. // ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ÇÔ¼ö¿¡¼­ leftÀÇ Å©±â°¡ Ç×»ó Å©µµ·Ï ¼³Á¤ // | Left | - | Right | // °¡ ¼º¸³ÇÑ´Ù´Â ÀüÁ¦ÇÏ¿¡ subtractÇÔ¼ö´Â ÀÛµ¿ÇÕ´Ï´Ù. // Ãʱ⿡´Â divideWithRemainderÇÔ¼ö¿¡¼­ // subtractÇÔ¼ö¸¦ this->subtract(*this, x)¿Í °°ÀÌ È£ÃâÇÏ¿© /* if (Left.len < Right.len) { add(Right, Left); return; } */ // ÀÌ ÇÊ¿äÇÏ¿´Áö¸¸, divide..ÇÔ¼öÀÇ ¾Ë°í¸®ÁòÀ» ´Ù¸¥ °ÍÀ¸·Î // ±³Ã¼ Çϸ鼭 subtractÇÔ¼ö¸¦ È£ÃâÇÏÁö ¾Ê°ÔµÇ¾î »èÁ¦ÇÏ¿´½À´Ï´Ù. // »©´Âµ¥ µÉ ¼öÀÖ´Â °¡Àå ±ä ±æÀÌ´Â Left.len Reallocate(Left.len); blocktype blk_temp = 0; // µÎ ºí·°ÀÇ Â÷¸¦ Àá½Ã ÀúÀåÇϱâ À§ÇØ // ÀÚ¸®³»¸² 󸮿ë // borrowIn : ÀÌÀü ÀÚ¸®¿¡¼­ ÀÚ¸®³»¸² ¹ß»ý? // borrowOut : Çö ÀÚ¸®¿¡¼­ ¿¬»êÀ¸·Î ÀÚ¸®³»¸² ¹ß»ý? bool borrowIn, borrowOut; index i; // ³·Àº ÀÚ¸® ¸¸Å­ ·çÇÁ¸¦ µ¹¸ç »¬¼À ¿¬»ê for(i = 0, borrowIn = false; i < Right.len; i++){ blk_temp = Left.blk[i] - Right.blk[i]; // ÀÚ¸® ³»¸²ÀÌ ¹ß»ýÇϸé // blk_temp > Left.blk[i] // blk_temp > Right.blk[i] // À§ µÎ°³¸¦ ¸ðµÎ ¸¸Á·ÇÑ´Ù. // ±×·¡¼­ µÎ °³Áß¿¡ Çϳª¸¸ »ç¿ëÇÏ¿© ºñ±³ÇØ ÁÖ¸éµÈ´Ù. borrowOut = (blk_temp > Left.blk[i]); if (borrowIn) { // Àü ÀÚ¸®¿¡¼­ ÀÚ¸®³»¸² ¹ß»ýÇߴ°¡? // BorrowInÀ¸·Î ÀÎÇÑ ÀÚ¸®³»¸² ¹ß»ý °¡´É¼º ó¸® borrowOut |= (blk_temp==0); blk_temp--; } blk[i] = blk_temp; borrowIn = borrowOut; } // blk[Right.len - 1]¿¡¼­ ÀÚ¸®³»¸² ¹ß»ýÇߴ°¡? // ¶ÇÇÑ, Å« °¡´É¼ºÀº ¾øÁö¸¸ ¿¬¼â ÀÚ¸®³»¸²ÀÌ °¡´ÉÇÏ´Ù // ex) 1000 - 1°ú °°Àº °æ¿ì¿Í ºñ½ÁÇÑ ¸Æ¶ô for(; borrowIn && i < Left.len; i++){ borrowIn = (Left.blk[i] == 0); blk[i] = Left.blk[i] - 1; } // ³ª¸ÓÁö´Â ±×´ë·Î ´ëÀÔ for(; i < Left.len; i++) blk[i] = Left.blk[i]; // ¿¬»ê °á°ú·Î »ý±â´Â ¼±µÎ 0ºí·°µéÀ» ¸ðµÎ Á¦°Å ZapLeadingZeros(); } void BigInteger::multiply(const BigInteger &Left, const BigInteger &Right) { // µÎ ¼öÀÇ Å©±â¸¦ °öÇÏ¿© this¿¡ ÀúÀåÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. // nÀÚ¸® * mÀÚ¸® °ö¼À °á°ú´Â ÃÖ´ë (n+m)ÀÚ¸®°¡ µË´Ï´Ù. Reallocate(Left.len + Right.len); Blkinit(); // µÎ 32ºñÆ®ÀÇ ¿¬»êÀ¸·Î´Â ÃÖ´ë 64ºñÆ®°¡ ³ª¿É´Ï´Ù. // µû¶ó¼­, µÎ ºí·ÏÀÇ ¿¬»ê°ªÀ» ÀúÀåÇϱâ À§ÇØ // unsigned __int64ÇüÀ¸·Î Àӽà ÀúÀå º¯¼ö¸¦ ¸¸µì´Ï´Ù. unsigned __int64 temp_res; // Àӽà ÀúÀå°ªÀ» ºí·Ï¿¡ ³Ö±â À§Çؼ­´Â 64ºñÆ®¸¦ // ´Ù½Ã 32ºñÆ®¾¿ ³ª´©¾î Áà¾ßÇÕ´Ï´Ù. blocktype blk_temp[2] = {0,}; /* * °ö¼À ¾Ë°í¸®ÁòÀº ÃʵîÇб³‹š ¹è¿ì´Â ¹æ½ÄÀ» »ç¿ëÇÏ¿´½À´Ï´Ù. * ´ë½Å ÇÑÀÚ¸®¾¿ °è»êÇÏ´Â°Ô ¾Æ´Ñ 32ºñÆ®¾¿ °è»êÇÏ´Â °Í»ÓÀÔ´Ï´Ù. * ÀÎÅͳݿ¡¼­ ÀÌ·± ¹æ½ÄÀ» 'Schoolbook Multiplication' À̶ó°í Çϳ׿ä. * Google¿¡¼­ Fast MultiplicationÀ» Ä¡¸é ¸¹Àº ÀÚ·á°¡ ³ª¿É´Ï´Ù. */ index i,j,k,l; for(i = 0; i < Left.len; i++){ temp_res = 0; for(j = 0; j < Right.len; j++){ // µÎ ºí·°À» °öÇÏ¿© 32ºñÆ®¾¿ ÂÉ°³¾î ÀúÀåÇÕ´Ï´Ù. temp_res = unsigned __int64(Left.blk[i]) * Right.blk[j]; blk_temp[0] = blocktype(temp_res); blk_temp[1] = blocktype(temp_res >> N); for (k = i + j, l = 0; l < 2; l++) { blk[k] += blk_temp[l]; // ´õÇߴµ¥ blk[k]¿¡¼­ ÀÚ¸® ¿Ã¸²ÀÌ ¹ß»ýÇÑ´Ù¸é!!! if (blk[k] < blk_temp[l]) { // ¿¬¼â ÀÚ¸®¿Ã¸²ÀÇ °æ¿ìµµ »ý°¢ÇÏ¿© // ¿¬¼â ÀÚ¸®¿Ã¸²ÀÌ ¹ß»ýÇÏÁö ¾ÊÀ» ¶§±îÁö // ´ÙÀ½ ÀÚ¸®µéÀ» 1 Áõ°¡½ÃŲ´Ù. for (;;) { blk[++k]++; if (blk[k] == 0) continue; else break; } } // blk_temp[0]¿¡ ´ëÇÑ °è»ê ÈÄ, // blk_temp[1]ÀÇ ¿¬»êÀ» À§ÇØ, k ÀçÁ¤ÀÇ k = i + j + 1; } } } // lenÀÇ ±æÀÌ´Â 'ÃÖ´ë' Left.len + Right.lenÀÌ µÉ ¼ö ÀÖÁö¸¸ // Left.len + Right.len - 1µµ µÉ ¼ö ÀÖ´Ù. if (blk[len - 1] == 0) len--; } void BigInteger::divideWithRemainder(const BigInteger &Divisor, BigInteger &Quotient) { /* * Á¦¼ö°¡ ÇÇÁ¦¼öº¸´Ù Å« °æ¿ì´Â ³ª´°¼ÀÀ» ÇÒ ÇÊ¿ä°¡ ¾ø½À´Ï´Ù. * ¸òÀº 0, ³ª¸ÓÁö´Â ÇÇÁ¦¼ö°¡ µÉÅ״ϱî¿ä. * ¿¬»êÀ» ÇÏÁö ¾Ê¾Æµµ µÇ±â ¶§¹®¿¡, ÀÌ¿Í °°Àº °æ¿ì´Â * »çÀü¿¡ Á¶°Ç¹®À¸·Î °É·¯Áִ°ÍÀÌ ¿¬»ê¼Óµµ¸¦ ºü¸£°Ô ÇØ ÁÙ¼ö ÀÖ½À´Ï´Ù. * ÇÏÁö¸¸ ÀÌ Á¶°Ç¹®¿¡¼­ ½Ã°£À» ¸¹ÀÌ Àâ¾Æ¸ÔÀ¸¸é ¾ÈµË´Ï´Ù. * * Á¦¼ö > ÇÇÁ¦¼ö ¸¦ ÆǺ°ÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀ¸·Î´Â * Á¤È®ÇÑ 1°¡Áö¿Í ´ë·«ÀûÀÎ 2°¡Áö ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù. * * 1. compareÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Å©±â°¡ Å«Áö ÆǺ°Çϱâ * Á¦ÀÏ Á¤È®ÇÑ ¹æ¹ýÀÌÁö¸¸, ¿À·¡ °É¸³´Ï´Ù. * Å« ¼ýÀÚÀÏ °æ¿ì´Â Á¦¼ö¿Í ÇÇÁ¦¼öÀÇ Å©±â°¡ °°´Ù¸é * for¹®À» ¼ö¹é¸¸¹øÀ» µ¹ ¼öµµ ÀÖ½À´Ï´Ù. * * 2. Á¦¼ö¿Í ÇÇÁ¦¼öÀÇ ºñÆ® ±æÀÌ Ã¼Å©Çϱâ * ºñÆ® ±æÀÌ´Â Á¦ÀÏ ³ôÀº ºñÆ®°¡ ¾îµð ÀÖ´ÂÁö¸¦ ³ªÅ¸³»´Â °Í°ú °°½À´Ï´Ù. * µû¶ó¼­, Á¦ÀÏ ³ôÀº ºñÆ®´Â °°Áö¸¸ Á¦¼ö°¡ Å« °æ¿ì´Â Á¦¿ÜÇÏ°í * ex) ÇÇÁ¦¼ö : 10(2), Á¦¼ö : 11(3) * ³ª¸ÓÁö´Â ÆǺ°°¡´É ÇÕ´Ï´Ù. * * 3. Á¦¼ö¿Í ÇÇÁ¦¼öÀÇ ºí·° ±æÀÌ ºñ±³ * °¡Àå ºü¸¥ ¹æ¹ýÀÔ´Ï´Ù. ´Ü¼øÇÏ°Ô Á¦¼ö¿Í ÇÇÁ¦¼öÀÇ * lenÀ» ºñ±³ÇÏ´Â °ÍÀ̱⠶§¹®ÀÔ´Ï´Ù. * ÇÏÁö¸¸, ±×¸¸Å­ ³õÄ¡´Â °æ¿ìµµ ¸¹½À´Ï´Ù. * * ¼¼ °¡Áö ¹æ¹ýÀ¸·Î Á¦¼ö¿Í ÇÇÁ¦¼öÀÇ Å©±â¸¦ ºñ±³ÇÒ ¼ö ÀÖ½À´Ï´Ù. * ±× Áß, °¡Àå ºü¸¥ 3¹ø° ¹æ¹ýÀ» »ç¿ëÇÏ°Ú½À´Ï´Ù. * ´Ù½Ã Çѹø ¸»¾¸µå¸®Áö¸¸, ÀÌ Á¶°ÇÀ» ½áÁÖÁö ¾Ê¾Æµµ * ¿¬»ê °úÁ¤À» ÅëÇØ ¸ò°ú ³ª¸ÓÁö¸¦ ±¸ÇÒ ¼ö ÀÖ½À´Ï´Ù. * ´Ù¸¸ ºÒÇÊ¿äÇÑ ¿¬»ê °úÁ¤À» °ÅÄ¡Áö ¾Ê±â À§Çؼ­ * °É·¯³»´Â °ÍÀ̹ǷΠ¸ðµç °æ¿ì¿¡ ´ëÇؼ­ * ±× °æ¿ì¸¦ »ìÇÊ ÇÊ¿ä´Â ¾ø½À´Ï´Ù. */ if (blklength() < Divisor.blklength()) { Quotient = _Zero; return; } // ÀÌÁ¦, (*this).len >= Divisor.len ÀÌ ¼º¸³ÇÕ´Ï´Ù. /* * ³ª´°¼ÀÀ» Á¤ÀÇÇÏ´Â µ¥¿¡´Â ÀÇ°ßÀÌ °¥¸³´Ï´Ù. * ¾ç¼ö¿Í ¾ç¼öÀÇ ³ª´°¼ÀÀº »ó°ü ¾øÁö¸¸ * ¾ç¼ö¿Í À½¼ö, À½¼ö¿Í À½¼öÀÇ ³ª´°¼À¿¡¼­ ±¸ÇöÇÑ »ç¶÷¸¶´Ù * Â÷ÀÌ°¡ ÀÖ½À´Ï´Ù. * ÀÌ ºÎºÐÀº ÄÄÆÄÀÏ·¯¸¶´Ùµµ °á°ú°ªÀÌ ´Þ¶óÁø´Ù°í ÇÕ´Ï´Ù. * Ç¥ÁØÀÌ Á¤ÀǵÇÁö ¾Ê¾Ò´Ù°í Çϳ׿ä.. * --------------------------------- * 2 / (-3) = 0 2 % (-3) = 2 * --------------------------------- * 2 / (-3) = -1 2 % (-3) = -1 * --------------------------------- * * 2 / (-3)ÀÇ ¼Ò¼ö±îÁöÀÇ ³ª´°¼ÀÀ» ±¸Çϸé * -0.66666666666666666666... ÀÔ´Ï´Ù. * ¿©±â¼­ ¼Ò¼öÁ¡À» ¹ö¸±Áö.. * ¾Æ´Ï¸é ¿Ã¸² ó¸® ÇÒÁö¿¡ µû¶ó °á°ú°¡ ´Þ¶óÁö´Â °ÍÀÔ´Ï´Ù. * Àü, À§¿¡ °ÍÀ» Åä´ë·Î ¸¸µé°Ú½À´Ï´Ù. * vc°¡ À§¿Í °°ÀÌ ³ª¿À±â ¶§¹®ÀÔ´Ï´Ù. * ¾Æ·¡´Â Matt¾¾°¡ ¸¸µç°Í¿¡¼­ Àú·¸°Ô ¸¸µì´Ï´Ù. */ /* Àü¹ÝÀûÀÎ ¹æ¹ý.. * ¾Ë°í¸®ÁòÀº ÃʱâÀÇ ¾Ë°í¸®Áò°ú ºñ½ÁÇÕ´Ï´Ù. * ÃʵîÇб³ ¶§, ¹è¿ì´ø ³ª´©±â ¹æ¹ýÀ» ±×´ë·Î »ç¿ëÇÕ´Ï´Ù. * Ãʱâ¿Í ´Ù¸¥ Á¡Àº Á» ´õ ºü¸£´Ù´Â °ÍÀÔ´Ï´Ù. * * (Ãʱ⠳ª´©±â ¾Ë°í¸®Áò) * 776 * ---------- * 159 | 123456 * 111300 * ------ * 12156 * 11130 * ------- * 1026 * 954 * ------ * 72 * * * (ÇöÀç ³ª´©±â ¾Ë°í¸®Áò) * 776 * ---------- * 159 | 123456 * 1113 * ------ * 1215 * 1113 * ------- * 1026 * 954 * ------ * 72 * * µÎ°³ÀÇ Â÷ÀÌÁ¡À» ¾Æ½Ã°Ú½À´Ï±î? * »¬¼À °úÁ¤ÀÌ ´Ù¸¨´Ï´Ù. * À§¿¡¼­´Â 123456 - 111300À» ±¸ÇÑ´Ù¸é * ¾Æ·¡¿¡¼­´Â 1234 - 1113À» ±¸ÇÕ´Ï´Ù! * Å« ¼ýÀÚ¶ó¸é ¾öû³­ ¼ÓµµÂ÷ÀÌ°¡ ¾Æ´Ò ¼ö ¾ø½À´Ï´Ù!! */ index i, j, k; unsigned int i2; blocktype temp; bool borrowIn, borrowOut; BigInteger orig(*this); length origLen = len; // °è»ê»ó, *this.blk[len]À» Á¢±ÙÇØ¾ß ÇÕ´Ï´Ù. // µû¶ó¼­, ¿À·ù¸¦ ¸·±âÀ§ÇØ ÀçÇÒ´ç ÇÕ´Ï´Ù. Reallocate(len + 1); Blkcopy(orig); blk[len-1] = 0; //memmove(blk, orig.blk, sizeof(blocktype) * origLen); // »©±â °ªÀ» ÀúÀåÇϱâ À§ÇØ »ç¿ëÇÕ´Ï´Ù. blocktype *subtractBuf = new blocktype[len]; memset(subtractBuf, 0, sizeof(blocktype) * len); // ¸òÀ» ¹Ì¸® ÇÒ´çÇÕ´Ï´Ù. Quotient.Allocate(origLen - Divisor.len + 1); // reallocate¿¡¼­ allocate·Î ¹Ù²Þ 9.14 Quotient.Blkinit(); // À§¿¡¼­ºÎÅÍ ºñÆ® Çϳª¾¿ °è»êÇسª°©´Ï´Ù. i = Quotient.len; while (i > 0) { i--; Quotient.blk[i] = 0; i2 = N; while (i2 > 0) { i2--; for (j = 0, k = i, borrowIn = false; j <= Divisor.len; j++, k++) { temp = blk[k] - Divisor.Get_LShiftedBlock(j, i2); borrowOut = (temp > blk[k]); if (borrowIn) { borrowOut |= (temp == 0); temp--; } subtractBuf[k] = temp; borrowIn = borrowOut; } for (; k < origLen && borrowIn; k++) { borrowIn = (blk[k] == 0); subtractBuf[k] = blk[k] - 1; } if (!borrowIn) { Quotient.blk[i] |= (blocktype(1) << i2); while (k > i) { k--; blk[k] = subtractBuf[k]; } } } } // Quotient.len != 1¿¡¼­ 0À¸·Î ¹Ù²Þ 9.14 if (Quotient.len != 0 && Quotient.blk[Quotient.len - 1] == 0) Quotient.len--; ZapLeadingZeros(); delete [] subtractBuf; // ¸ò°ú ³ª¸ÓÁöÀÇ ºÎÈ£ÁöÁ¤ Quotient.sign = (sign == Divisor.sign) ? Positive : Negative; if (Quotient.len == 0 /*&& Quotient.blk[0] == 0*/) Quotient.sign = Zero; if (len == 0 /*&& blk[0] == 0*/) sign = Zero; // 0ºÎÈ£ º¯°æ Á¶°Ç ¹Ù²Þ 9.14 } const BigInteger BigInteger::operator -() const { BigInteger temp(*this); if (temp.sign == Zero) return temp; temp.sign = (sign == Positive) ? Negative : Positive; return temp; } const BigInteger abs(const BigInteger &x) { BigInteger temp(x); if (temp.sign == BigInteger::Negative) temp.sign = BigInteger::Positive; return temp; } const BigInteger BigInteger::add(const BigInteger &x) const { // µÑ Áß Çϳª°¡ 0ÀÌ¸é ´Ù¸¥ ¼ö¸¦ ¸®ÅÏÇÏ¸é µË´Ï´Ù. if (sign == Zero) return x; if (x.sign == Zero) return *this; BigInteger temp; // ºÎÈ£°¡ °°Àº°æ¿ì.. if (sign == x.sign) { temp.add(*this, x); temp.sign = sign; } // µÎ ¼öÀÇ ºÎÈ£°¡ ´Ù¸£´Ù¸é, »¬¼À°ú °°½À´Ï´Ù. else { int cmp; // compareÇÔ¼ö´Â this¿Í xÀÇ 'Å©±â'¸¦ ºñ±³ÇÕ´Ï´Ù. cmp = compare(x); if (cmp == 0) ; // ¿¬»ê ¾øÀÌ 0¸®ÅÏ else if (cmp == 1) { // this > xÀÎ °æ¿ì temp.subtract(*this, x); temp.sign = sign; } else { // x > thisÀÎ °æ¿ì temp.subtract(x, *this); temp.sign = x.sign; } } return temp; } const BigInteger BigInteger::operator +(const BigInteger &x) const { return add(x); } const BigInteger & BigInteger::operator +=(const BigInteger &x) { //BigInteger temp(*this); return *this = add(x); } const BigInteger BigInteger::subtract(const BigInteger &x) const { BigInteger temp; // µÑ Áß Çϳª°¡ 0ÀÏ ¶§ ó¸® if (x.sign == Zero) return *this; if (sign == Zero) { temp = x; return -temp; } // µÎ ¼öÀÇ ºÎÈ£°¡ ´Ù¸£´Ù¸é Å©±â´Â ´õÇØÁö°í // ºÎÈ£´Â this¸¦ µû¸£¸é µË´Ï´Ù. if (sign != x.sign) { temp.add(*this, x); temp.sign = sign; } // µÎ ¼öÀÇ ºÎÈ£°¡ °°À» ¶§ else { int cmp; // this¿Í xÀÇ 'Å©±â'ºñ±³ cmp = compare(x); if ( cmp == 0 ) ; // °°´Ù¸é °á°ú´Â 0 else if ( cmp == 1 ) { // this > xÀÎ °æ¿ì temp.subtract(*this, x); temp.sign = sign; } else { // this < xÀÎ °æ¿ì temp.subtract(x, *this); // thisÀÇ ºÎÈ£¿¡ µû¶ó °á°ú°ªÀÇ ºÎÈ£°¡ ´Þ¶óÁü // Zero°¡ ³ª¿À´Â °æ¿ì´Â À§¿¡¼­ ó¸®ÇßÀ¸¹Ç·Î // Zero°¡ ³ª¿Ã ¼ö´Â ¾ø´Ù. temp.sign = (sign ==Positive) ? Negative : Positive; } } return temp; } const BigInteger BigInteger::operator -(const BigInteger &x) const { return subtract(x); } const BigInteger & BigInteger::operator -=(const BigInteger &x) { return *this = subtract(x); } const BigInteger BigInteger::multiply(const BigInteger &x) const { BigInteger temp; // µÎ ¼öÁß 0ÀÌ ÀÖÀ¸¸é °öÇϳª¸¶³ª 0ÀÔ´Ï´Ù. if (sign == Zero || x.sign == Zero) return temp; temp.multiply(*this, x); // µÎ ¼öÀÇ ºÎÈ£°¡ °°À¸¸é +, ´Ù¸£¸é -°¡ µË´Ï´Ù. temp.sign = (sign == x.sign) ? Positive : Negative; return temp; } const BigInteger BigInteger::operator *(const BigInteger &x) const { return multiply(x); } const BigInteger & BigInteger::operator *=(const BigInteger &x) { return *this = multiply(x); } const BigInteger BigInteger::divide(const BigInteger &x) const { BigInteger q, r(*this); if (x.sign == Zero) { #if defined(_DEBUG) throw "0À¸·Î ³ª´­ ¼ö ¾ø½À´Ï´Ù."; #else return q; // 0 ¸®ÅÏ #endif } r.divideWithRemainder(x, q); return q; } const BigInteger BigInteger::mod(const BigInteger &x) const { BigInteger q, r(*this); if (x.sign == Zero) { #if defined(_DEBUG) throw "0À¸·Î ³ª´­ ¼ö ¾ø½À´Ï´Ù."; #else return q; // 0 ¸®ÅÏ #endif } r.divideWithRemainder(x, q); return r; } const BigInteger BigInteger::operator /(const BigInteger &x) const { return divide(x); } const BigInteger BigInteger::operator %(const BigInteger &x) const { return mod(x); } const BigInteger & BigInteger::operator /=(const BigInteger &x) { return *this = divide(x); } const BigInteger & BigInteger::operator %=(const BigInteger &x) { return *this = mod(x); } void BigInteger::PlusOne() { index i; bool carry = true; for (i = 0; i < len && carry; i++) { ++blk[i]; carry = (blk[i] == 0); } if (carry) { Reallocate(len + 1); Blkinit(); blk[i] = 1; } } void BigInteger::MinusOne() { index i; bool borrow = true; for (i = 0; borrow; i++) { borrow = (blk[i] == 0); --blk[i]; } if (blk[len - 1] == 0) len--; } BigInteger & BigInteger::operator ++() { if (sign == Negative) { MinusOne(); if (len == 0) sign = Zero; } else { PlusOne(); sign = Positive; } return *this; } const BigInteger BigInteger::operator ++(int dummy) { BigInteger temp(*this); ++(*this); return temp; } BigInteger & BigInteger::operator --() { if (sign == Positive) { MinusOne(); if (len == 0) sign = Zero; } else { PlusOne(); sign = Negative; } return *this; } const BigInteger BigInteger::operator --(int dummy) { BigInteger temp(*this); --(*this); return temp; } BigInteger pow(const BigInteger &x, const BigInteger &y) { // xÀÇ y½ÂÀ» ±¸ÇÕ´Ï´Ù. /* * 1. x°¡ 0ÀÏ ¶§ * ¤¡. y°¡ 0ÀÏ ¶§ -> ¿¡·¯! * ¤¤. ³ª¸ÓÁö -> 0 * 2. x°¡ 0ÀÌ ¾Æ´Ò ¶§ * ¤¡. y°¡ 0ÀÏ ¶§ -> 1 * ¤¤. y°¡ À½¼ö -> ¿¡·¯! * ¤§. y°¡ ¾ç¼ö -> x ^ y */ if (x.sign == BigInteger::Zero) { #if defined(_DEBUG) if (y.sign == BigInteger::Zero) throw "Á¤ÀÇÇÒ ¼ö ¾ø½À´Ï´Ù."; #else return _Zero; #endif } if (y.sign == BigInteger::Zero) return _One; else if (y.sign == BigInteger::Negative) { #if defined(_DEBUG) throw "Áö¼ö°¡ À½¼öÀÔ´Ï´Ù."; #else return _Zero; #endif } BigInteger res(x); BigInteger count(y); while (--count) res *= x; return res; } BigInteger factorial(const BigInteger &x) { // x! À» ±¸ÇÏ´Â ÆÑÅ丮¾ó ÇÔ¼öÀÔ´Ï´Ù. // ÇöÀç´Â ´Ü¼øÈ÷ x * (x-1) * ..... (2) * (1) // ó·³ °öÇϱ⠿¬»êÀ¸·Î ±¸ÇÏ¿© x°¡ ¸¹ÀÌ Ä¿Áö°Ô µÇ¸é // ¼Óµµ°¡ ¾öû³ª°Ô ´À·ÁÁý´Ï´Ù. // 1000! ±îÁö´Â ´«±ô¦ÇÒ »çÀÌ¿¡ ±¸ÇÒ ¼ö ÀÖ½À´Ï´Ù. // computer by computer.. // 0!Àº 1·Î Á¤ÀÇÇÕ´Ï´Ù. // À½¼öÀÇ ÆÑÅ丮¾óµµ ±¸ÇÒ ¼ö ÀÖ°Ô ÇÏ¿´½À´Ï´Ù. // À½¼öÀÇ ÆÑÅ丮¾óÀÇ Á¤ÀÇ´Â... // x * (x + 1) * (x + 2) .... (-2) * (-1) // ·Î Á¤ÀÇ ÇÏ¿´½À´Ï´Ù. if (x.sign == BigInteger::Zero) return _One; BigInteger res(x); BigInteger count(x); // x°¡ ¾ç¼ö¸é count¸¦ °¨¼ö½ÃÅ°¸ç °öÇϱâ // À½¼ö¸é Áõ°¡½ÃÅ°¸ç °öÇϱâ if (x.sign == BigInteger::Positive){ while (--count) res *= count; } else { while (++count) res *= count; } return res; } BigInteger gcd(BigInteger x,BigInteger y) { // x¿Í yÀÇ ÃÖ´ë °ø¾à¼ö¸¦ ±¸ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. // À¯Å¬¸®µå È£Á¦¹ý ¾Ë°í¸®ÁòÀ» »ç¿ëÇÕ´Ï´Ù. // ³ª¸ÓÁö¸¸ Áß¿äÇÏ¸ç ¸òÀº ÇÊ¿ä¾ø½À´Ï´Ù. // À½¼öÀÇ ÃÖ´ë°ø¾à¼ö´Â ¿¡·¯·Î ó¸®ÇÏ¸ç ±¸ÇÏÁö ¾Ê½À´Ï´Ù. BigInteger trash; if (x.sign == BigInteger::Zero || y.sign == BigInteger::Zero) return _Zero; if (x.sign == BigInteger::Negative || y.sign == BigInteger::Negative) { #if defined(_DEBUG) throw "À½¼öÀÇ ¿¬»êÀº ±ÝÁöÇÕ´Ï´Ù."; #else return _Zero; #endif } for (;;) { if (y.sign == BigInteger::Zero) return x; x.divideWithRemainder(y, trash); if (x.sign == BigInteger::Zero) return y; y.divideWithRemainder(x, trash); } } BigInteger lcm(BigInteger x,BigInteger y) { // ÃÖ¼Ò°ø¹è¼ö¸¦ ±¸ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. // gcdÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ±¸Çϸç // lcm(x, y) = x * y / gcd(x, y)°¡ // ¼º¸³ÇÔÀ» ÀÌ¿ëÇÏ¿© ±¸ÇÕ´Ï´Ù. BigInteger _gcd = gcd(x, y); // ÃÖ´ë °ø¾à¼ö°¡ 0À̶ó¸é // ÃÖ´ë °ø¹è¼öµµ 0ÀÔ´Ï´Ù. if (_gcd.sign == BigInteger::Zero) return _Zero; return x * y / _gcd; }