2010-10-06 10 views
5

मुझे नीचे बड़ी हेक्साडेसिमल संख्याओं के साथ कुछ अंकगणित करने की आवश्यकता है, लेकिन जब मैं आउटपुट करने का प्रयास करता हूं तो मुझे अतिप्रवाह त्रुटि संदेश मिल रहा है "हेक्साडेसिमल संख्या> 0xffffffff गैर-पोर्टेबल", पोर्टेबल के बारे में संदेश, या अधिकतम 32-बिट हेक्स मान FFFFFFFF।मैं 64-बिट हेक्स/दशमलव अंकगणितीय कैसे कर सकता हूं और पर्ल में स्ट्रिंग के रूप में हेक्स में पूर्ण संख्या आउटपुट कर सकता हूं?

जिनमें से सभी का मतलब है कि मानक भाषा और आउटपुट दिनचर्या केवल 32 बिट मानों का सामना करती हैं। मुझे 64-बिट मानों की आवश्यकता है और मैंने बहुत सारे शोध किए हैं, लेकिन मुझे कुछ भी नहीं मिला है कि दोनों अंकगणित को सक्षम बनाता है और हेक्स में बड़ी संख्या में आउटपुट करता है।

my $result = 0x00000200A0000000 + 
      (($id & 0xFFFFF) * 2) + (($id/0x100000) * 0x40000000); 

तो, निम्न मानों के साथ $ आईडी के लिए मैं $result मिलना चाहिए:

$id = 0, $result = 0x00000200A0000000 
$id = 1, $result = 0x00000200A0000002 
$id = 2, $result = 0x00000200A0000004 

मैं यह कैसे कर सकते हैं?

कारण यहाँ के साथ मेरी अनिर्णायक शोध के परिणाम है, क्यों:

  • How can I do 64-bit arithmetic in Perl?

  • How can I sum large hexadecimal values in Perl? अस्पष्ट, निश्चित सटीक और कोई उदाहरण नहीं जवाब।

  • Integer overflow गैर निर्णायक

  • Integer overflow गैर निर्णायक

  • bigint काम, गणित या उत्पादन

  • bignum उदाहरण मेरी समस्या के करीब नहीं के बारे में कोई जानकारी।

  • How can I sprintf a big number in Perl? उदाहरण दिए गए मेरे लिए काफी जानकारी नहीं है: हेक्स काम या अंकगणितीय के साथ सौदा नहीं करता है।

  • Re: secret code generator कुछ Fleximal के उपयोग के उदाहरण, चर के उत्पादन मूल्य के लिए to_str का उल्लेख है, लेकिन 1) मैं नहीं दिख रहा है कि कैसे चर सौंपा गया था और 2) मैं त्रुटि "विधि कॉल नहीं कर सकता" to_str " पैकेज या ऑब्जेक्ट के बिना संदर्भ" जब मैं का उपयोग करके अपना कोड चलाता हूं।

  • String to Hex मठ :: BigInt का उपयोग करने का उदाहरण है जो मेरे लिए काम नहीं करता है - अभी भी अतिप्रवाह त्रुटि मिलती है।

  • Is there a 64-bit hex()? लगभग वहाँ - लेकिन हेक्स में बड़ी संख्या में outputting के साथ सौदा नहीं है, यह केवल दशमलव के बात करती है।

  • CPAN Math:Fleximal गणित करता है, लेकिन वहाँ के लिए वास्तव में उत्पादन हेक्स में मूल्य अभी भी

  • sprintf प्रतीत नहीं करता है संख्या अधिक से अधिक से निपटने के लिए सक्षम होने के लिए किसी भी तरह हो प्रतीत नहीं होता है 32-बिट्स से, संतृप्त एफएफएफएफएफएफएफएफ संदेश प्राप्त करें।


संपादित करें: अपडेट - नई आवश्यकता और आपूर्ति समाधान - कृपया टिप्पणियां

चास की पेशकश कर सकते हैं। ओवेन्स का जवाब अभी भी स्वीकार्य और उत्कृष्ट है (मेरे लिए भाग 2 काम, नए पर्ल के लिए भाग 1 संस्करण की कोशिश नहीं की है, हालांकि मैं दूसरों को इसकी पुष्टि करने के लिए आमंत्रित करता हूं)।

हालांकि, एक और आवश्यकता परिणामस्वरूप मूल आईडी से वापस को परिवर्तित करने में सक्षम होना था।

इसलिए मैंने ऐसा करने के लिए कोड लिखा है, यहां @Chas सहित पूर्ण समाधान है। ओवेन्स मूल समाधान, इस नए आवश्यकता के लिए कार्यान्वयन के बाद:

#!/usr/bin/perl 

use strict; 
use warnings; 
use bigint; 

use Carp; 

sub bighex { 
    my $hex = shift; 

    my $part = qr/[0-9a-fA-F]{8}/; 
    croak "$hex is not a 64-bit hex number" 
     unless my ($high, $low) = $hex =~ /^0x($part)($part)$/; 

    return hex("0x$low") + (hex("0x$high") << 32); 
} 

sub to_bighex { 
    my $decimal = shift; 
    croak "$decimal is not an unsigned integer" 
      unless $decimal =~ /^[0-9]+$/; 

    my $high = $decimal >> 32; 
    my $low = $decimal & 0xFFFFFFFF; 

    return sprintf("%08x%08x", $high, $low); 
} 

for my $id (0 ,1, 2, 0xFFFFF, 0x100000, 0x100001, 0x1FFFFF, 0x200000, 0x7FDFFFFF) { 
    my $result = bighex("0x00000200A0000000"); 
    $result += (($id & 0xFFFFF) * 2) + (($id/0x100000) * 0x40000000); 

    my $clusterid = to_bighex($result); 

# the convert back code here: 
my $clusterid_asHex = bighex("0x".$clusterid); 
my $offset = $clusterid_asHex - bighex("0x00000200A0000000"); 
my $index_small_units = ($offset/2) & 0xFFFFF; 
my $index_0x100000_units = ($offset/0x40000000) * 0x100000; 
my $index = $index_0x100000_units + $index_small_units; 


    print "\$id = ".to_bighex($id). 
      " clusterid = ".$clusterid. 
      " back to \$id = ".to_bighex($index). 
      " \n"; 
} 

http://ideone.com/IMsp6 में इस कोड को बाहर की कोशिश करो।

+1

उत्पादन: ivsize'? – ysth

+0

यह एक त्रुटि संदेश नहीं है, यह एक चेतावनी है। विशेष रूप से, एक ऐसा कोड जो आपका कोड काम कर सकता है जहां perl 64 बिट पूर्णांक का उपयोग करता है लेकिन यह 32 बिट पूर्णांक का उपयोग नहीं करता है। यदि वास्तव में आपके पास हमेशा 64 बिट पूर्णांक होते हैं, तो उन्हें 'चेतावनी' पोर्टेबल के साथ अक्षम करें ";' – ysth

+0

@ysth यह एक बुरा विचार है। कोड अब पोर्टेबल नहीं होगा। उन्हें बंद करके चेतावनी को शांत करना एक बुरा अभ्यास है। एक बेहतर समाधान के लिए मेरा जवाब देखें। –

उत्तर

12
#!/usr/bin/perl 

use strict; 
use warnings; 

use bigint qw/hex/; 

for my $id (0 ,1, 2) { 
    my $result = hex("0x00000200A0000000") + 
     (($id & 0xFFFFF) * 2) + (($id/0x100000) * 0x40000000); 
    printf "%d: %#016x\n", $id, $result; 
} 

bigint pragma एक संस्करण है कि बड़ी संख्या में संभाल कर सकते हैं के साथ hex समारोह बदल देता है। यह पारदर्शी रूप से गणितीय ऑपरेटरों को लक्ष्य प्लेटफॉर्म पर स्याही की बजाय बड़ी चींटियों से निपटने में सक्षम बनाता है।

नोट, यह केवल पर्ल 5.10 और बाद में काम करता है। आप पर्ल 5 के पिछले संस्करण चला रहे हैं, तो आप इस कोशिश कर सकते हैं: `पर्ल वी के

#!/usr/bin/perl 

use strict; 
use warnings; 
use bigint; 

use Carp; 

sub bighex { 
    my $hex = shift; 

    my $part = qr/[0-9a-fA-F]{8}/; 
    croak "$hex is not a 64-bit hex number" 
     unless my ($high, $low) = $hex =~ /^0x($part)($part)$/; 

    return hex("0x$low") + (hex("0x$high") << 32); 
} 

sub to_bighex { 
    my $decimal = shift; 
    croak "$decimal is not an unsigned integer" 
      unless $decimal =~ /^[0-9]+$/; 

    my $high = $decimal >> 32; 
    my $low = $decimal & 0xFFFFFFFF; 

    return sprintf("%08x%08x", $high, $low); 
} 

for my $id (0 ,1, 2) { 
    my $result = bighex("0x00000200A0000000"); 
    $result += (($id & 0xFFFFF) * 2) + (($id/0x100000) * 0x40000000); 
    print "$id ", to_bighex($result), "\n"; 
} 
+1

+1: उत्कृष्ट उत्तर ... – dawg

+1

कभी-कभी आपको पोर्टेबिलिटी की आवश्यकता नहीं होती है। और एक 64 बिट समर्थन perl पर 64 बिट गणित करने के लिए बड़े हथौड़ा तक पहुंचने के लिए बस मुझे अपील नहीं करता है। वह printf() कॉल जो आप पहले से ही खिड़की से पोर्टेबिलिटी फेंकता है। – ysth

+1

@ysth हाँ, मैंने देखा और एक दूसरा संस्करण लिखा जो सभी 32-बिट मशीनों पर काम करना चाहिए। –

संबंधित मुद्दे

 संबंधित मुद्दे