हेमिंग में फ्लोट 754


29

आप के रूप में दी जाएगी इनपुट एक पूर्णांक kसे रेंज में -4503599627370496(-2 52 करने के लिए) 4503599627370496(2 52 )। जैसा कि सर्वविदित है , इस रेंज में पूर्णांकों को दोहरे-सटीक फ्लोटिंग-पॉइंट मानों के रूप में दर्शाया जा सकता है।

आपको चाहिये उत्पादन आलोचनात्मक वजन की एन्कोडिंग की (लोगों की संख्या) kमें binary64 प्रारूप । यह साइन के लिए 1 बिट का उपयोग करता है, एक्सपोर्टर के लिए 11 बिट्स (एक ऑफसेट के साथ एन्कोडेड), और मंटिसा के लिए 52; विवरण के लिए उपरोक्त लिंक देखें।

एक उदाहरण के रूप में , संख्या 22को इस रूप में दर्शाया गया है

0 10000000011 0110000000000000000000000000000000000000000000000000

चूंकि वहाँ हैं 5, आउटपुट है 5

ध्यान दें कि धीरज परिणाम को प्रभावित नहीं करता है, इसलिए आप आउटपुट की गणना करने के लिए अपने मशीन के वास्तविक आंतरिक प्रतिनिधित्व का उपयोग कर सकते हैं।

अतिरिक्त नियम

परीक्षण के मामलों

22                ->   5
714               ->   6
0                 ->   0
1                 ->  10
4503599627370496  ->   5
4503599627370495  ->  55
1024              ->   3
-1024             ->   4
-4096             ->   5
1000000000        ->  16
-12345678         ->  16

1
क्या आप चाहते हैं कि फ़ंक्शंस उनके इनपुट्स को फ़्लोटिंग-पॉइंट binary64फॉर्मेट में पहले से ही स्वीकार कर सकें, अगर वे चाहें तो? कुछ लोग (स्वयं सहित, शुरू में) इस प्रश्न की व्याख्या कर रहे थे कि कार्यों को C के जैसे पूर्णांक प्रकार के रूप में इनपुट स्वीकार करना आवश्यक है long। सी में, आप तर्क दे सकते हैं कि भाषा आपके लिए परिवर्तित हो जाएगी, जैसे आप कॉल करते हैं sqrt((int)foo)। लेकिन कुछ x86 मशीन-कोड asm उत्तर हैं (जैसे codegolf.stackexchange.com/a/136360/30206 और मेरा) जो दोनों मान रहे थे कि हमें 64-बिट पूर्णांक इनपुट स्वीकार करना था। binary64मान स्वीकार करने से 5 बाइट बचती हैं।
पीटर कॉर्डेस

यदि ऐसा है, तो सीमित-सीमा के बारे में वह सब सामान सिर्फ उस स्थिति में है जब कोई व्यक्ति बाइनरी 64 बिट-पैटर्न में रूपांतरण को हैक करना चाहता था बजाय टाइप-पिंगिंग के? या टाइप-पिंगल के बिना भाषाओं के लिए? हम्म, एक दिलचस्प चुनौती एक binary64आधार 2 पूर्णांक के घातांक और मंटिसा को जोड़ने के लिए हो सकती है । यदि आपको उन्हें अलग से संभालने की आवश्यकता है, तो यह सभी बिट्स पर टाइप-पेन्ट और लूप के अलावा कुछ करने के लायक हो सकता है।
पीटर कॉर्डेस

2
@PeterCordes हाँ, आप एक फ़्लोटिंग-पॉइंट संख्या के रूप में इनपुट कर सकते हैं। सीमित सीमा यह सुनिश्चित करने के लिए है कि फ्लोटिंग-पॉइंट प्रतिनिधित्व सटीक है
लुइस मेंडो

ठीक है धन्यवाद। मुझे लगता है कि आप एक फ़ंक्शन लिखने का विकल्प छोड़ना चाहते थे जो कि लेता है long, इसलिए आप किसी भी बाइनरी 64 को नहीं कह सकते double, क्योंकि सभी डबल्स पूर्णांक नहीं हैं। लेकिन सभी पूर्णांक-मूल्यवान doubles को longऔर सीमा तक परिवर्तित किया जा सकता है long। (जैसा कि आप बताते हैं, रिवर्स सच नहीं है। आपको doubleडिफ़ॉल्ट राउंडिंग मोड मानकर निकटतम अभ्यावेदन मिलता है)। वैसे भी, यह सवाल स्थापित करने का एक पूरी तरह से वैध तरीका था; मैंने अभी इसे ध्यान से नहीं पढ़ा था। <
पीटर कॉर्ड्स

"ध्यान दें कि धीरज परिणाम को प्रभावित नहीं करता है, इसलिए आप आउटपुट की गणना करने के लिए अपने मशीन के वास्तविक आंतरिक प्रतिनिधित्व को दोहरे-सटीक मानों का उपयोग कर सकते हैं।" जब तक आपकी मशीन IEEE फ्लोटिंग पॉइंट फॉर्मेट का उपयोग नहीं करती ...
जैरी जेरेमिया

जवाबों:


8

MATL , 5 बाइट्स

3Z%Bz

इसे ऑनलाइन आज़माएं!

मेरे MATLAB उत्तर का सटीक लिप्यंतरण। ध्यान दें कि इनपुट और आउटपुट निहित हैं। लुइस मेंडो के लिए -2 बाइट्स धन्यवाद।

3Z%   % Typecast: changes input (implicitly taken and converted to double) to uint64 without changing underlying bits
B     % Convert integer to array of 1s and 0s
z     % Count nonzero entries

33

x86_64 मशीन भाषा (लिनक्स), 16 बाइट्स

0:       f2 48 0f 2a c7          cvtsi2sd %rdi,  %xmm0
5:       66 48 0f 7e c0          movq     %xmm0, %rax
a:       f3 48 0f b8 c0          popcnt   %rax,  %rax
f:       c3                      retq

में एक एकल 64-बिट पूर्णांक पैरामीटर को स्वीकार RDIकरता है, इसे फ़्लोटिंग-पॉइंट मान में परिवर्तित करता है XMM0, उन बिट्स को वापस स्टोर RAXकरता है, और उसके बाद के हैमिंग वेट की गणना करता है RAX, जिसके परिणामस्वरूप RAXयह कॉलर को वापस किया जा सकता है।

एक प्रोसेसर की आवश्यकता होती है जो POPCNTनिर्देश का समर्थन करता है , जो Intel Nehalem, AMD बार्सिलोना, और बाद में माइक्रोआर्किटेक्चर होगा।

इसे ऑनलाइन करने का प्रयास करें! , संकलन करें और निम्नलिखित C प्रोग्राम चलाएं:

#include<stdio.h>
const char g[]="\xF2\x48\x0F\x2A\xC7\x66\x48\x0F\x7E\xC0\xF3\x48\x0F\xB8\xC0\xC3";
#define f(x) ((int(*)(long))g)(x)

int main(int a){
  printf("%d\n",f(22));
  printf("%d\n",f(714));
  printf("%d\n",f(0));
  printf("%d\n",f(1));
  printf("%d\n",f(4503599627370496L));
  printf("%d\n",f(4503599627370495L));
  printf("%d\n",f(1024));
  printf("%d\n",f(-1024));
  printf("%d\n",f(-4096));
  printf("%d\n",f(1000000000));
  printf("%d\n",f(-12345678));
}

2
+1, नौकरी के लिए सही उपकरण! यह एकमात्र समय हो सकता है कि x86 वैध रूप से गोल्फ भाषाओं के साथ प्रतिस्पर्धा कर सकता है, या जेली को हरा सकता है। :)
DJMcMayhem

2
ईडब्ल्यू, एटी एंड टी सिंटैक्स? आप objdump -drwC -Mintelइंटेल सिंटैक्स में जुदा करने के लिए उपयोग कर सकते हैं । यदि आपके पास रजिस्टर में एक पॉइंटर था जिसे आप स्टोर / रीलोड करने के लिए उपयोग कर सकते हैं, तो आप बाइट्स को movaps [rsi], xmm0/ के साथ बचा सकते हैं popcnt rax, [rsi]। (मूव्स केवल 3 बाइट्स हैं, Movq से 2 छोटे हैं।) लेकिन यहां मदद नहीं करता है, क्योंकि [rsp-24]2 अतिरिक्त बाइट्स (SIB को आधार के रूप में RSP का उपयोग करने से प्लस प्लस 8) लेता है। और उन अतिरिक्त बाइट्स को स्टोर और पुनः लोड दोनों में आवश्यक है। ओह ठीक है, मैंने सोचा था कि मैंने एक बचत देखी है, लेकिन नहीं: /
पीटर कॉर्ड्स

मैंने एक कस्टम कॉलिंग कन्वेंशन के साथ 4 बाइट्स बचाए । या अभी भी 2 बाइट्स को एक ही कॉलिंग कन्वेंशन के साथ x87 निर्देशों का उपयोग करके बचाएं।
पीटर कॉर्डेस

1
@DJMcMayhem: शायद एकमात्र समय नहीं है। चरम फाइबोनैचि चुनौती पर अभी भी कोई गोल्फ-भाषा के जवाब नहीं हैं (फ़िब (1 बिलियन) के पहले 1000 अंक प्रिंट करें, और मेरे x86 मशीन कोड उत्तर (105 बाइट्स तेज़, या 101 बाइट्स जो 1 मिनट के बजाय 5 मिनट में चलते हैं) कुछ अन्य उत्तरों की तुलना में बहुत बड़ा नहीं है, और वे सभी भाषाओं में विस्तारित-सटीक पूर्णांक के साथ निर्मित हैं।
पीटर कॉर्ड्स

2
या एक सरल चुनौती, (और एक प्रदर्शन की आवश्यकता के बिना), क्रोमा-कुंजी एक पूर्णांक की एक सरणी सम्मिश्रण करता है । मेरा मशीन-कोड उत्तर पाइथ उत्तर की लंबाई का आधा है।
पीटर कॉर्ड्स

11

सी (जीसीसी) , 82 68 बाइट्स

9 बाइट्स नील को धन्यवाद।

बुराई चल बिंदु बिट स्तर हैकिंग

s;f(long n){double d=n;n=*(long*)&d;for(s=0;n;n*=2)s+=n<0;return s;}

इसे ऑनलाइन आज़माएं!


मुझे पता था कि आप सबसे पहले होंगे, मुझे बस भाषा की उम्मीद नहीं थी :-D
लुइस मेंडो

@LuisMendo मैंने सोचा था कि यह उस भाषा में सुविधाजनक होगा ... मुझे अन्य भाषाओं का पता नहीं है जो ऐसा कर सकते हैं
लीक नून

2
दूसरे रास्ते को शिफ्ट करके 9 बाइट्स बचाएं: ;long l=... ;l*=2;)s+=l<0;...
नील

1
इस कोर्स के लिए 64-बिट के साथ सी कार्यान्वयन की आवश्यकता होती है long। यह x86-64 लिनक्स पर काम करता है, लेकिन विंडोज पर विफल होगा। मैं "64-बिट के साथ जीसीसी" कहने का सुझाव longदूंगा, क्योंकि जीसीसी कई प्लेटफार्मों पर चलता है, उनमें से कई अलग-अलग एबीआई के साथ हैं।
पीटर कॉर्ड्स

1
@ पीटर की टिप्पणी है कि मैंने एक संपादन में "LP64" क्यों जोड़ा। मैंने दूसरे पाठ को भी फिर से व्यवस्थित किया जो मुझे लगा कि यह एक अधिक तार्किक क्रम है। मुझे लगता है कि आप उस बदलाव को पसंद नहीं करते थे और इसे वापस ले आते थे, लेकिन LP64 एक मानक शब्द है जो ABI का वर्णन करता है, जहां longs और संकेत 64-बिट मान हैं (ILP64 की तुलना में, जहां ints 64-बिट या LLP64 हैं,) जैसा कि विंडोज पर उपयोग किया जाता है, जहां केवल लंबे लोंग और पॉइंटर्स 64-बिट हैं और लॉन्ग अभी भी 32-बिट हैं)। हो सकता है कि मुझे अधिक विवरण, या प्रासंगिक विकिपीडिया लेख के लिए एक इनलाइन लिंक जोड़ा जाना चाहिए।
कोडी ग्रे

8

पायथन 3 , 72 71 बाइट्स

लिन को 1 बाइट धन्यवाद।

lambda n:n and(bin(1020+len(bin(abs(n))))+bin(abs(n))).count('1')-(n>0)

इसे ऑनलाइन आज़माएं!

व्याख्या

बाइनरी 64 प्रारूप में तीन घटक होते हैं:

  • पहला बिट साइन बिट है, जो 1यदि संख्या नकारात्मक है
  • अगले 11 बिट्स 1023 जोड़ा के साथ घातांक को स्टोर करते हैं
  • अगले 52 बिट्स महत्व या मोंटिसा स्टोर करते हैं।

n and(…)-(n>0)एक बाइट कम है, नहीं?
लिन

या int-> फ्लोट, या किसी भी चीज के लिए तैरता है।
user2357112

8

सी (जीसीसी) , 47 बाइट्स

f(double n){n=__builtin_popcountl(*(long*)&n);}

यह पोर्टेबल नहीं है; यह बिना संकलक झंडे के x86_64 चल रहे लिनक्स पर gcc 7.1.1 के साथ परीक्षण किया गया था।

इसे ऑनलाइन आज़माएं!


1
इनपुट एक पूर्णांक होना चाहिए। या यह बताने के लिए फोन करने वाले को संभालने के अंतर्निहित रूपांतरण द्वारा ठीक है longके लिए doubleकॉल स्थल पर?
पीटर कॉर्डेस

1
इसके अलावा, संकलक व्यवहार का एक अस्थायी पर निर्भर छोड़ने के लिए होने के लिए nमें raxसंयुक्त राष्ट्र-अनुकूलित कोड के साथ बहुत घटिया है। यदि आप सक्षम करते हैं तो यह टूट जाता है -O3, इसलिए यह सामान्य रूप से केवल gcc नहीं है, यह x86-64 पर gcc है जिसमें 64-बिट longऑप्टिमाइज़ेशन अक्षम है। यदि आप उन सभी आवश्यकताओं को अपने उत्तर में डालते हैं, तो मुझे बहुत खुशी होगी। मुझे लगता है कि ऐसे प्लेटफ़ॉर्म हैं, जिनका समर्थन 64-बिट है, longलेकिन ऐसा होता है कि popcountlपरिणाम को रिटर्न-वैल्यू रजिस्टर के अलावा किसी अन्य रजिस्टर में छोड़ दिया जाता है ।
पीटर कॉर्डेस

1
मैंने गणितीय अर्थों में पूर्णांक लिया। मैंने अपने परीक्षण वातावरण के चश्मे को जोड़ दिया है, क्योंकि मुझे यकीन नहीं है कि जीसीसी, x86-64 और 64-बिट लोंग पर्याप्त हैं। कहा कि, कम से कम x86 पर, रिटर्न-कम फ़ंक्शन gcc (और tcc) के साथ अधिक बार नहीं की तुलना में काम करते हैं।
डेनिस

हाँ, मैं प्रश्न को फिर से पढ़ रहा था, और मैं मानता हूँ कि अर्ग को doubleठीक होना चाहिए। यह बेस 2 प्रारूप में इसे स्वीकार करने के लिए फ़ंक्शन की आवश्यकता के बारे में कुछ नहीं कहता है। और हां, जीसीसी के विभिन्न संस्करण अलग-अलग कोड का उत्सर्जन कर सकते हैं, इसलिए यह महत्वपूर्ण है, भी। (मजेदार तथ्य: बिना -mpopcnt, जीसीसी popcntइन्सान का उपयोग नहीं किया जाएगा , और इसे अनुकरण करने के लिए निर्देशों का एक अनुक्रम निकल जाएगा। कुछ आर्किटेक्चर के पास पॉपकान्ट निर्देश नहीं है, इसलिए __builtin_popcountlहमेशा कुछ अनुक्रमों का उपयोग करना होगा)
पीटर कॉर्ड्स

हां, __builtin_*अवैध निर्देशों को उत्पन्न करने से बचने के लिए कई (अधिकांश?) कार्यों के पास विरासत संस्करण हैं। उपलब्ध होने पर ही -march=nativeउपयोग करता popcntqहै।
डेनिस


6

सी (जीसीसी), 63 बाइट्स

f(double d){long s=0,n=*(long*)&d;for(;n;n*=2)s+=n<0;return s;}

यह समाधान @ LeakyNun के उत्तर पर आधारित है, लेकिन क्योंकि वह अपने स्वयं के उत्तर में सुधार नहीं करना चाहता है, मैं यहां और अधिक गोल्फ संस्करण पोस्ट कर रहा हूं।

इसे ऑनलाइन आज़माएं


2
मुझे अत्यधिक संदेह है कि कोई भी अपने उत्तर में सुधार नहीं करना चाहता है
मिस्टर एक्सकोडर

1
@ Mr.Xcoder। ठीक है, मैं इसे यहां रखूंगा जब तक कि वह अपना जवाब संपादित नहीं करता। यदि वह संपादित नहीं करना चाहता है, तो यह यहां रहेगा। मैंने उनके उत्तर पर एक टिप्पणी के रूप में इस सुधार को पोस्ट किया और उन्होंने इसे अस्वीकार कर दिया।

1
मुझे लगता है कि इनपुट को एक पूर्णांक प्रकार होना चाहिए और वास्तविक नहीं।
सीलिंगकॉट

3
@ ThePirateBay मैंने अपने जवाब पर आपकी टिप्पणी नहीं देखी और मैं अभी भी इसे नहीं देख रहा हूं।
लीक नून

9
सुधार का सुझाव देने या अपना खुद का जवाब पोस्ट करने का निर्णय आपका है, लेकिन 6 मिनट शायद ही एक घंटे के बारे में है
डेनिस

5

सी #, 81 70 68 बाइट्स

d=>{unsafe{long l=*(long*)&d,s=0;for(;l!=0;l*=2)s-=l>>63;return s;}}

@Leaky नन के लिए 11 बाइट्स धन्यवाद सहेजें।
2 बाइट्स @Neil की बदौलत सहेजे गए।

इसे ऑनलाइन आज़माएं! उपयोगSystem.BitConverter.DoubleToInt64Bitsunsafeकोड के बजाय क्योंकि मैं इसके साथ काम करने के लिए TIO प्राप्त नहीं कर सका।

पूर्ण / स्वरूपित संस्करण:

namespace System
{
    class P
    {
        static void Main()
        {
            Func<double, long> f = d =>
            {
                unsafe
                {
                    long l = *(long*)&d, s = 0;

                    for (; l != 0; l *= 2)
                        s -= l >> 63;
                    return s;
                }
            };

            Console.WriteLine(f(22));
            Console.WriteLine(f(714));
            Console.WriteLine(f(0));
            Console.WriteLine(f(1));
            Console.WriteLine(f(4503599627370496));
            Console.WriteLine(f(4503599627370495));
            Console.WriteLine(f(1024));
            Console.WriteLine(f(-1024));
            Console.WriteLine(f(-4096));
            Console.WriteLine(f(1000000000));
            Console.WriteLine(f(-12345678));

            Console.ReadLine();
        }
    }
}

for(;l!=0;l*=2)और आपको टर्नरी की आवश्यकता नहीं होगी
लीके नन

@ LeakyNun धन्यवाद मैं अपने सिर को उस उम्र के लिए खरोंच रहा था।
द लीथलकोडर

क्या आप उपयोग कर सकते हैं s-=l>>31?
नील

@ नील काम करने के लिए प्रकट नहीं होता है। मुझे लगता है कि आप को बदलने का मतलब है s+=l<0?1:0?
TheLethalCoder

मेरी गलती; lएक लंबा है, तो इसकी जरूरत है s-=l>>63?
नील

4

अजगर २ , 69 बाइट्स

-12 बाइट्स, @ ASCII- केवल के लिए धन्यवाद

lambda n:bin(*unpack('Q',pack('d',n))).count('1')
from struct import*

इसे ऑनलाइन आज़माएं!




@ Mr.Xcoder को !बाइट ऑर्डर की आवश्यकता नहीं है क्योंकि यहां कोई फर्क नहीं पड़ता
केवल


@ ASCII- केवल अनपैक पैक करें। साभार: D
डेड पोसम

4

जावास्क्रिप्ट (ईएस 6), 81 80 77 बाइट्स

f=
n=>new Uint8Array(Float64Array.of(n).buffer).map(g=i=>i&&g(i^i&-i,x++),x=0)|x
<input oninput=o.textContent=f(this.value)><pre id=o>0

संपादित करें: @Annauld के लिए 1 बाइट धन्यवाद सहेजा गया। सहेजे गए 3 बाइट्स @DocMax के लिए धन्यवाद।


क्या आप g(i^i&-i,x++)-1 बाइट के लिए कर सकते हैं ?
Arnauld

@Arnauld मुझे आश्चर्य हुआ कि क्या कोई गोल्फर बिट ट्वेल्ड था, इसे खोजने के लिए धन्यवाद!
नील

1
-3 अधिक अगर आप के new Float64Array([n])साथ बदलेंFloat64Array.of(n)
DocMax

4

x86-64 मशीन कोड, 12 बाइट्स के लिए int64_t इनपुट के

के लिए 6 बाइट्स doubleइनपुट के

आवश्यक popcntईसा विस्तार (CPUID.01H:ECX.POPCNT [Bit 23] = 1 )।

(या 13 बाइट्स अगर arg में जगह को संशोधित करने के लिए ऊपरी 32 में कचरा छोड़ने के बजाय सभी 64-बिट लिखने की आवश्यकता होती है। मुझे लगता है कि यह तर्क देना उचित है कि कॉलर शायद कम 32b को वैसे भी लोड करना चाहेगा, और xx 280 प्रत्येक 32-बिट ऑपरेशन के साथ 32 से 64 तक अनुमानित है। फिर भी, यह कॉलर को करने से रोकता है add rbx, [rdi] कुछ या कुछ है।)

x87 निर्देश अधिक स्पष्ट SSE2 cvtsi2sd/ movq( @ सीलिंगकैट के उत्तर में प्रयुक्त ) से कम होते हैं, और एक [reg]एड्रेसिंग मोड एक ही आकार का होता है reg: बस एक मॉड / आरएम बाइट।

ट्रिक को मेमोरी को पास करने के तरीके के साथ आना था, बिना मोड्स को संबोधित करने के लिए बहुत सारे बाइट्स की आवश्यकता के बिना। (जैसे स्टैक पर गुजरना इतना अच्छा नहीं है।) सौभाग्य से, नियम पढ़ने / लिखने की अनुमति देता है, या अलग आउटपुट आर्ग देता है , इसलिए मुझे बस कॉल करने वाला मिल सकता है मुझे एक पॉइंटर पास करने के लिए जो मुझे लिखने की अनुमति है।

हस्ताक्षर के साथ C से कॉल करने योग्य: void popc_double(int64_t *in_out); परिणाम का केवल कम 32b मान्य है, जो शायद C के लिए अजीब है, लेकिन asm के लिए स्वाभाविक है। (इसे ठीक करने के लिए अंतिम स्टोर पर एक आरईएक्स उपसर्ग की आवश्यकता होती है ( mov [rdi], rax), इसलिए एक और बाइट।) विंडोज पर, को बदल rdiदेंrdx , के बाद से विंडोज x86-64 सिस्टम वी ABI का उपयोग नहीं करता है।

एनएएसएम लिस्टिंग। TIO लिंक में डिस्सैड के बिना स्रोत कोड है।

  1  addr    machine      global popcnt_double_outarg
  2          code         popcnt_double_outarg:
  3                           ;; normal x86-64 ABI, or x32: void pcd(int64_t *in_out)
  4 00000000 DF2F             fild qword  [rdi]    ; int64_t -> st0
  5 00000002 DD1F             fstp qword  [rdi]    ; store binary64, using retval as scratch space.
  6 00000004 F3480FB807       popcnt rax, [rdi]
  7 00000009 8907             mov    [rdi], eax    ; update only the low 32b of the in/out arg
  8 0000000B C3               ret
    # ends at 0x0C = 12 bytes

इसे ऑनलाइन आज़माएं! इसमें एक _startपरीक्षण कार्यक्रम शामिल है जो इसे एक मान देता है और बाहर निकलने की स्थिति के साथ बाहर निकलता है = popcnt वापसी मूल्य। (इसे देखने के लिए "डीबग" टैब खोलें।)

अलग इनपुट / आउटपुट पॉइंटर्स पास करना भी काम करेगा (x86-64 SystemV ABI में rdi और rsi), लेकिन तब हम 64-बिट इनपुट को यथोचित रूप से नष्ट नहीं कर सकते हैं या केवल लिखते समय 64-बिट आउटपुट बफर की आवश्यकता को आसानी से सही ठहरा सकते हैं कम 32 ब।

यदि हम यह तर्क देना चाहते हैं कि हम इनपुट पूर्णांक के लिए एक सूचक ले सकते हैं और इसे नष्ट कर सकते हैं, जबकि आउटपुट वापस कर सकते हैं rax, तो बस से चूक कर सकते mov [rdi], eaxहैं popcnt_double_outarg, इसे 10 बाइट्स तक ला सकते हैं।


मूर्खतापूर्ण कॉलिंग-कन्वेंशन ट्रिक्स के बिना वैकल्पिक, 14 बाइट्स

स्टैक को स्क्रैच स्पेस के रूप में उपयोग करें, pushइसे वहां लाने के लिए। 3 के बजाय 2 बाइट्स में रजिस्टरों को कॉपी करने के लिए push/ popका उपयोग करें mov rdi, rsp। ( [rsp]हमेशा एक एसआईबी बाइट की आवश्यकता होती है, इसलिए इसका rspउपयोग करने वाले तीन निर्देशों से पहले कॉपी करने के लिए 2 बाइट खर्च करने लायक है।)

इस हस्ताक्षर के साथ C से कॉल करें: int popcnt_double_push(int64_t);

 11                               global popcnt_double_push
 12                               popcnt_double_push:
 13 00000040 57                       push   rdi         ; put the input arg on the stack (still in binary integer format)
 14 00000041 54                       push   rsp         ; pushes the old value (rsp updates after the store).
 15 00000042 5A                       pop    rdx         ; mov      rdx, rsp
 16 00000043 DF2A                     fild   qword [rdx]
 17 00000045 DD1A                     fstp   qword [rdx]
 18 00000047 F3480FB802               popcnt rax,  [rdx]
 19 0000004C 5F                       pop    rdi         ; rebalance the stack
 20 0000004D C3                       ret
    next byte is 0x4E, so size = 14 bytes.

doubleप्रारूप में इनपुट स्वीकार करना

सवाल सिर्फ यह कहता है कि यह एक निश्चित सीमा में पूर्णांक है, ऐसा नहीं है कि इसे बेस 2 बाइनरी पूर्णांक प्रतिनिधित्व में होना चाहिए। doubleइनपुट स्वीकार करने का मतलब है कि अब x87 का उपयोग करने का कोई मतलब नहीं है। (जब तक आप एक कस्टम कॉलिंग कन्वेंशन का उपयोग नहीं करते हैं जहां doubles x87 रजिस्टरों में पारित हो जाते हैं। तब स्टैक के नीचे रेड-ज़ोन में स्टोर करें, और वहां से पॉपकॉइन करें।)

11 बाइट्स:

 57 00000110 66480F7EC0               movq    rax, xmm0
 58 00000115 F3480FB8C0               popcnt  rax, rax
 59 0000011A C3                       ret

लेकिन हम 6-बाइट संस्करण बनाने के लिए उसी पास-दर-संदर्भ ट्रिक का उपयोग कर सकते हैं: int pcd(const double&d);

 58 00000110 F3480FB807               popcnt  rax, [rdi]
 59 00000115 C3                       ret

6 बाइट्स



3

MATLAB, 36 बाइट्स

@(n)nnz(de2bi(typecast(n,'uint64')))

इस तथ्य का उपयोग करना कि de2biन केवल से कम है dec2bin, बल्कि एएससीआईआई 48, 49 के बजाय लोगों और शून्य में भी परिणाम प्रदान करता है।


3

जावा (64, 61, 41 बाइट्स)

मानक पुस्तकालय (जावा एसई 5+) का उपयोग करके पूरी तरह से सीधा:

int f (long n) {लौंग लॉन्ग। बिटकाउंट (डबल। डबललॉन्गबिट्स (एन)) ;;

केविन क्रूज़सेन द्वारा योगदान (जावा एसई 5+):

int f(Long n){return n.bitCount(Double.doubleToLongBits(n));}

केविन क्रूज़सेन द्वारा योगदान (जावा एसई 8+, लैम्ब्डा फ़ंक्शन):

n->n.bitCount(Double.doubleToLongBits(n))

अच्छी तरह से किया! :-)
लीक नून

1
मुझसे अच्छा जवाब, +1। आप के रूप में पैरामीटर Long nका उपयोग करके तीन बाइट्स को गोल्फ कर सकते हैं और n.bitCount(...)इसके बजाय उपयोग कर सकते हैं Long.bitCount(...)। इसके अलावा, यदि आप जावा 8+ का उपयोग करते हैं, तो आप इसे n->n.bitCount(Double.doubleToLongBits(n))( 41 बाइट्स )
केविन क्रूज़सेन

2

बस एक अलग, अधिक सुरक्षित करने की कोशिश करने के लिए- TheLethalCoder के दृष्टिकोण, मैं इस के साथ आया (यह एक दयालु सी # इस तरह के लंबे नाम हैं):

सी # (.NET कोर) , 76 + 13 बाइट्स

d=>Convert.ToString(BitConverter.DoubleToInt64Bits(d),2).Split('1').Length-1

इसे ऑनलाइन आज़माएं!

बाइट काउंट में 13 बाइट्स शामिल हैं using System;। पहले मुझे doubleएक longही बाइनरी प्रतिनिधित्व करने के लिए कन्वर्ट करने की आवश्यकता है , फिर मैं इसे एक बाइनरी में बदल सकता हूं string, और फिर मैं 1बस स्ट्रिंग को विभाजित करके और सबस्ट्रिंग माइनस 1 की गिनती करके एस गिनता हूं ।


अच्छा विकल्प है लेकिन आपको usingअपनी बाइट गिनती में शामिल करने की आवश्यकता है ।
TheLethalCoder

95 बाइट्स के लिए लाइनक का उपयोग केवल कुछ और namespace System.Linq;{d=>Convert.ToString(BitConverter.DoubleToInt64Bits(d),2).Count(c=>c>48)}:। हालाँकि मैंने इसका परीक्षण नहीं किया है, लेकिन यह काम करना चाहिए।
द लीथल कोडर

@ TheLethalCoder यह काम करता है, लेकिन मैंने Linq से बचने की कोशिश की इसलिए मुझे दूसरा usingनिर्देश नहीं जोड़ना पड़ा ।
चार्ली

1
जब आप दूसरा जोड़ते हैं जब namespaceवह काम आता है। लेकिन हाँ इस मामले में लिनक से बचना थोड़ा सस्ता था। यदि आप इसे बाइट्स को बचाने के लिए इसे छोटा करना चाहते हैं, तो आपके पास यह दृष्टिकोण के साथ टिप्पणी करना चाहता था।
TheLethalCoder

@TheLethalCoder, Sum(c=>c&1)छोटा है। याSum()-768
पीटर टेलर


1

डीसी, 79 बाइट्स

[pq]su[-1r]st0dsb?dd0=u0>tsa[1+]ss[la2%1=slb1+sblad2/sa1<r]dsrxlb1022+sa0lrx+1-

स्टैक के ऊपर आउटपुट छोड़ा गया है।
मैं बाद में एक स्पष्टीकरण जोड़ूंगा।

इसे ऑनलाइन आज़माएं!

ध्यान दें कि नकारात्मक संख्याएँ पूर्ववर्ती हैं _, नहीं -



1

सी, 67 बाइट्स

int i;g(char*v){int j=v[i/8]&1<<i%8;return!!j+(++i<64?g(v):(i=0));}

नियंत्रण कोड और परिणाम

#define R     return
#define u32 unsigned
#define F        for
#define P     printf

int main()
{/*           5   6 0 10                5               55    3      4       16*/
 double v[]={22,714,0,1 ,4503599627370496,4503599627370495,1024, -1024, -12345678};
 int i; 

 F(i=0;i<9;++i)
     P("%f = %d\n", v[i], g(&v[i]));
 R 0;
}

>tri4
22.000000 = 5
714.000000 = 6
0.000000 = 0
1.000000 = 10
4503599627370496.000000 = 5
4503599627370495.000000 = 55
1024.000000 = 3
-1024.000000 = 4
-12345678.000000 = 16

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