سؤال

بالنظر إلى مقال ويكيبيديا نقطة radix., ، كيف يمكن للمرء حساب المكافئ الثنائي 10.1 أو ما يعادل عشرية 17.17؟ بالنسبة إلى السابق، ما هو ما يعادل الثنائي العاشر؟ لهذا الأخير، تمثيل عرافة 17/100؟

أبحث عن خوارزمية أكثر من الحلول لتلك الأمثلة فقط.

هل كانت مفيدة؟

المحلول

لتحويل عشري 10.1 إلى ثنائي، افصل الأجزاء العددية والكسرية وتحويل كل منهما بشكل منفصل.

لتحويل الجزء الصحيح، استخدم تقسيم عدد صحيح متكرر بنسبة 2، ثم اكتب الباقي بترتيب عكسي:

10/2 = 5 باقي 0

5/2 = 2 الباقي 1

2/2 = 1 الباقي 0

1/2 = 0 ما تبقى 1

الجواب: 1010.

لتحويل الجزء الكسري، استخدم الضرب المتكرر بنسبة 2، وطرح الجزء الأمثل في كل خطوة. تمثل الأجزاء الصحيحة، حسب جيل، رقمك الثنائي:

0.1 * 2 = 0.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

0.8 * 2 = 1.6

0.6 * 2 = 1.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

... (دورة تكرر إلى الأبد)

لذلك Decimal 0.1 ثنائي 0.000110011001100 ...

(للحصول على شرح أكثر تفصيلا، انظر الروتين dec2bin_i () و dec2bin_f () في مقالتي http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ .)

للحصول على السداسي عشري، استخدم نفس الإجراء، باستثناء مقسمي / مضاعف من 16 بدلا من 2. يجب تحويل الأجزاء العبقية والأجزاء العددية أكبر من 9 إلى أرقام Hex مباشرة: 10 يصبح A، 11 يصبح ب، ...، 15 يصبح F وبعد

نصائح أخرى

رقم إنهاء (رقم يمكن تمثيله بعدد محدود من الأرقام)1 في قاعدة ب1, ، قد ينتهي كونه رقم غير مهم في قاعدة مختلفة ب2. وبعد على العكس، عدد عدم الإنهاء في قاعدة واحدة ب1 قد تتحول إلى رقم إنهاء في قاعدة ب2.

الرقم 0.1.10 عند تحويلها إلى ثنائي رقم غير مهم، كما هو 0.1710 عند تحويلها إلى رقم سداسي عشري. ولكن ينهي رقم 0.13 في Base 3، عند تحويلها إلى Base 10 هو عدم الإنهاء، رقم التكرار 0. (3)10 (يدل على أن الرقم 3 يكرر). وبالمثل، تحويل 0.110 إلى ثنائي و 0.1710 إلى سداسي عشري، ينتهي المرء بأرقام عدم الإنهاء المتكررة 0.0 (0011)2 و 0.2 (B851E)16

لهذا السبب، عند تحويل هذا الرقم من قاعدة واحدة إلى أخرى، قد تجد نفسك في الاضطرار إلى تقريب الرقم بدلا من وجود تمثيل دقيق تماما.

الخوارزمية بسيطة للغاية، ولكن في الممارسة العملية يمكنك القيام بالكثير من التعديلات مع طاولات البحث والسجلات لتسريعها. ولكن بالنسبة للخوارزمية الأساسية، قد تجرب شيئا مثل هذا:

shift=0;

while v>=base,  v=v/base, shift=shift+1;  

Next digit: 
if v<1.0 && shift==0, output the decimal point
else 
   D=floor(v)
   output D
   v=v-D
v=v*base
shift = shift-1
if (v==0) exit;
goto Next Digit

قد تقوم أيضا بوضع اختبار في هناك لإيقاف الطباعة بعد N أرقام لعشرات العشرات الأطول المتكررة.

"المكافئ الثنائي" لعشر واحد هو نصف واحد، أي بدلا من 1/10 ^ 1، إنه 1/2 ^ 1.

يمثل كل رقم قوة اثنين. الأرقام وراء نقطة radix هي نفسها، من أنها تمثل فقط 1 على قوة اثنين:

 8 4 2 1 . 1/2 1/4 1/8 1/16 

لذلك لمدة 10.1، من الواضح أنك تحتاج إلى "8" و "2" لجعل الجزء 10. 1/2 (0.5) أكثر من اللازم، 1/4 (0.25) هو أكثر من اللازم، 1/8 (0.125) أكثر من اللازم. نحتاج إلى 1/16 (0.0625)، والتي سوف تترك لنا مع 0.0375. 1/32 هو 0.03125، لذلك يمكننا أن نأخذ ذلك أيضا. حتى الآن لدينا:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32
 1 0 1 0    0   0   0   1     1

مع خطأ 0.00625. 1/64 (0.015625) و 1/128 (0.0078125) كلاهما أكثر من اللازم، 1/256 (0.00390625) سيعمل:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
 1 0 1 0    0   0   0   1     1    0   0     1

مع خطأ 0.00234375.

لا يمكن التعبير عن .1 بالضبط في ثنائي (لا يمكن التعبير عن 1/3 تماما بالضبط). اعتمادا على المكان الذي تضع فيه باديكس، يجب أن تتوقف في النهاية أن تتوقف، وربما جولة، وقبول الخطأ.

قبل أن أكون في ضوء ذلك في ضوء مكتبة GMP الخاصة بي، إليك حيث حصلت على محاولة جعل كود PHP Rick Rican's PHP عام لأي قاعدة من 2 إلى 36.

Function dec2base_f(ByVal ddecimal As Double, ByVal nBase As Long, ByVal dscale As Long) As String
    Const BASES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 'up to base 36
    Dim digitCount As Long
    Dim wholeNumber As Double
    Dim digit As String * 1
    digitCount = 0
    dscale = max(dscale, Len(CStr(ddecimal)) - Len("0."))
    Dim baseary_f As String
    baseary_f = "0."
    Do While ddecimal > 0 And digitCount < dscale
        ddecimal = ddecimal * nBase
        digit = Mid$(BASES, Fix(ddecimal) + 1)
        baseary_f = baseary_f & digit '"1"
        ddecimal = ddecimal - Fix(ddecimal)
        digitCount = digitCount + 1
    Loop
    dec2base_f = baseary_f
End Function

Function base2dec_f(ByVal baseary_f As String, nBase As Double) As Double
    Const BASES As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Dim decimal_f As Double
    Dim i As Long
    Dim c As Long
    For i = Len(baseary_f) To Len("0.") + 1 Step -1
        c = InStr(BASES, Mid$(baseary_f, i, 1)) - 1
        decimal_f = decimal_f + c
        decimal_f = decimal_f / nBase
    Next
    base2dec_f = decimal_f
End Function

Debug.Print base2dec_f(dec2base_f(0.09, 2, 200), 2) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 8, 200), 8) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 16, 200), 16) --> 0.09
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top