पूर्णांक हेरफेर के माध्यम से एक IEEE 754 64-बिट बाइनरी फ्लोटिंग पॉइंट नंबर लागू करें


12

(मैंने प्रश्न "सी" को समय के लिए टैग कर दिया है, लेकिन अगर आप एक और भाषा के बारे में जानते हैं जो यूनियनों का समर्थन करती है, तो आप इसे भी पढ़ सकते हैं।)

आपका कार्य + - * /निम्नलिखित संरचना के लिए चार मानक गणितीय ऑपरेटरों का निर्माण करना है :

union intfloat{
    double f;
    uint8_t h[8];
    uint16_t i[4];
    uint32_t j[2]; 
    uint64_t k;
    intfloat(double g){f = g;}
    intfloat(){k = 0;}
}

इस तरह के ऑपरेशन खुद ही कभी पूर्णांक भाग में हेरफेर करते हैं या पहुंचते हैं (इसलिए ऑपरेशन के दौरान कभी भी दोहरे के साथ तुलना नहीं करते हैं), और परिणाम बिल्कुल समान है (या कार्यात्मक रूप से समकक्ष, जैसे गैर-संख्यात्मक परिणामों के मामले में NaN) जैसे कि संबंधित गणितीय ऑपरेशन को doubleइसके बजाय सीधे लागू किया गया था ।

आप चुन सकते हैं कि कौन सा पूर्णांक भाग हेरफेर करने के लिए है, शायद विभिन्न ऑपरेटरों के बीच अलग-अलग का उपयोग करके भी। (आप यूनियन के किसी भी क्षेत्र से "अहस्ताक्षरित" को हटाने का विकल्प चुन सकते हैं, हालांकि मुझे यकीन नहीं है कि आप ऐसा करना चाहते हैं।)

आपका स्कोर चार संचालकों में से प्रत्येक के लिए वर्णों में कोड की लंबाई का योग है। सबसे कम स्कोर जीतता है।

IEEE 754 विनिर्देशन से अपरिचित हम में से उन लोगों के लिए, यहाँ विकिपीडिया पर इसके बारे में एक लेख दिया गया है।


संपादन:

03-06 08:47 इंटफ्लोट स्ट्रक्चर में कंस्ट्रक्टर जोड़े। आपको मैन्युअल रूप से डबल / आदि सेट करने के बजाय उन्हें परीक्षण के लिए उपयोग करने की अनुमति है।


1
ओह! बताओ तुम्हारे पास एक उपाय है।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

4
हम्म् ... शायद यह बेहतर होगा के रूप intstructमें परिभाषित करने के लिए uint8_8, uint16_tऔर इतने पर के पूर्ण आकार के रूप में short, intऔर इतने पर मानक द्वारा परिभाषित नहीं हैं (प्रत्येक प्रकार का एक न्यूनतम आकार है और आकार में एक सख्त आदेश है, लेकिन बस)।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

1
मुझे लगता है कि यह एक महान (और चुनौतीपूर्ण) अभ्यास है भले ही असंगठित हो
जॉन ड्वोरक

3
यह प्रश्न इस बात का उपयोग कर सकता है कि कैसे राउंडिंग को संभाला जाए और एक अच्छा टेस्ट सूट हो।
पीटर टेलर

4
मुझे यकीन है कि यह कल्पना में है, लेकिन असली कल्पना कुछ सौ अमरीकी डालर की लागत वाली है। संभवतः ऐसे विवरण हैं जो मुफ्त में उपलब्ध हैं, लेकिन IMO प्रश्न पूछने वाले पर उस तरह का विवरण शामिल करने के लिए होना चाहिए (या किसी साइट का लिंक कम से कम जो कुछ वर्षों में अभी भी होने की संभावना है) प्रश्नकर्ता उत्तर देने के बजाय प्रश्न को वास्तव में क्या चाहता है, यह जानने के लिए आवश्यक सामग्री की खोज करने के लिए स्वयं को जाना।
पीटर टेलर

जवाबों:


11

सी ++, ~ 1500 चार्ट

फ़्लोट्स को 8000-बाइनरी-अंक निश्चित-बिंदु प्रतिनिधित्व में विस्तारित करता है, उस पर संचालन करता है, फिर वापस धर्मान्तरित करता है।

// an "expanded" float.                                                                                                         
// n is nan, i is infinity, z is zero, s is sign.                                                                               
// nan overrides inf, inf overrides zero, zero overrides digits.                                                                
// sign is valid unless nan.                                                                                                    
// We store the number in fixed-point, little-endian.  Binary point is                                                          
// at N/2.  So 1.0 is N/2 zeros, one, N/2-1 zeros.                                                                              
#define N 8000
struct E {
  int n;
  int i;
  int z;
  long s;
  long d[N];
};
#define V if(r.n|r.i|r.z)return r
// Converts a regular floating-point number to an expanded one.                                                                 
E R(F x){
  long i,e=x.k<<1>>53,m=x.k<<12>>12;
  E r={e==2047&&m!=0,e==2047,e+m==0,x.k>>63};
  if(e)m+=1L<<52;else e++;
  for(i=0;i<53;i++)r.d[2925+e+i]=m>>i&1;
  return r;
}
E A(E x,E y){
  int i,c,v;
  if(x.s>y.s)return A(y,x);
  E r={x.n|y.n|x.i&y.i&(x.s^y.s),x.i|y.i,x.z&y.z,x.i&x.s|y.i&y.s|~x.i&~y.i&x.s&y.s};V;
  if(x.s^y.s){
    c=0;
    r.z=1;
    for(i=0;i<N;i++){
      v=x.d[i]-y.d[i]-c;
      r.d[i]=v&1;c=v<0;
      r.z&=~v&1;
    }
    if(c){x.s=1;y.s=0;r=A(y,x);r.s=1;}
  }else{
    c=0;
    for(i=0;i<N;i++){
      v=x.d[i]+y.d[i]+c;
      r.d[i]=v&1;c=v>1;
    }
  }
  return r;
}
E M(E x, E y){
  int i;
  E r={x.n|y.n|x.i&y.z|x.z&y.i,x.i|y.i,x.z|y.z,x.s^y.s};V;
  E s={0,0,1};
  for(i=0;i<6000;i++)y.d[i]=y.d[i+2000];
  for(i=0;i<4000;i++){
    if(x.d[i+2000])s=A(s,y);
    y=A(y,y);
  }
  s.s^=x.s;
  return s;
}
// 1/d using Newton-Raphson:                                                                                                    
// x <- x * (2 - d*x)                                                                                                           
E I(E d){
  int i;
  E r={d.n,d.z,d.i,d.s};V;
  E t={};t.d[4001]=1;
  for(i=N-1;i>0;i--)if(d.d[i])break;
  E x={0,0,0,d.s};x.d[N-i]=1;
  d.s^=1;
  for(i=0;i<10;i++)x=M(x,A(t,M(d,x)));
  return x;
}
// Convert expanded number back to regular floating point.                                                                      
F C(E x){
  long i,j,e,m=0;
  for(i=N-1;i>=0;i--)if(x.d[i])break;
  for(j=0;j<N;j++)if(x.d[j])break;
  if(i>0&x.d[i-53]&(j<i-53|x.d[i-52])){E y={0,0,0,x.s};y.d[i-53]=1;return C(A(x,y));}
  if(i<2978){e=0;for(j=0;j<52;j++)m+=x.d[j+2926]<<j;}
  else if(i<5024){e=i-2977;for(j=0;j<52;j++)m+=x.d[i+j-52]<<j;}
  else x.i=1;
  if(x.z)e=m=0;
  if(x.i){e=2047;m=0;}
  if(x.n)e=m=2047;
  F y;y.k=x.s<<63|e<<52|m;return y;
}
// expand, do op, unexpand                                                                                                      
F A(F x,F y){return C(A(R(x),R(y)));}
F S(F x,F y){y.k^=1L<<63;return A(x,y);}
F M(F x,F y){return C(M(R(x),R(y)));}
F D(F x,F y){return C(M(R(x),I(R(y))));}

मैं एक सटीक गोल्फ की गिनती प्राप्त करने के लिए सभी रिक्त स्थान और नई लाइनों को हटाने के लिए बहुत आलसी हूं, लेकिन यह लगभग 1500 अक्षर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.