2008-11-19 13 views
7

हमारे पास कुछ पूर्णांक अंकगणित है जो ऐतिहासिक कारणों से PHP पर समान कार्य करना है क्योंकि यह कुछ स्थाई रूप से टाइप की गई भाषाओं में करता है। चूंकि हमने आखिरी बार PHP को अपग्रेड करने के लिए व्यवहार को बदल दिया है। असल में हम निम्नलिखित सूत्र का उपयोग कर रहे हैं:फोर्स PHP पूर्णांक ओवरफ़्लो

function f($x1, $x2, $x3, $x4) 
{ 
    return (($x1 + $x2)^$x3) + $x4; 
} 

हालांकि, यहां तक ​​रूपांतरण के साथ:

function f($x1, $x2, $x3, $x4) 
{ 
    return intval(intval(intval($x1 + $x2)^$x3) + $x4); 
} 

मैं अभी भी पूरी तरह से गलत संख्या के साथ समाप्त कर रहा हूँ ...

उदाहरण के लिए, $ x 1 के साथ = -1580033017, $ x2 = -2072974554, $ x3 = -1170476976) और $ x4 = -1007518822, मैं PHP में -30512150 और सी # में 1617621783 के साथ समाप्त होता हूं।

बस एक साथ $ x 1 और $ x2 जोड़ने मैं सही जवाब नहीं मिल सकता है:

सी # में मैं मिल

(-1580033017 + -2072974554) = 641959725 

PHP में:

intval(intval(-1580033017) + intval(-2072974554)) = -2147483648 

जो रूप में ही है:

intval(-1580033017 + -2072974554) = -2147483648 

मुझे "इंटेगर ओवरफ्लोएड" फ़ंक्शन या कुछ लिखने पर कोई फर्क नहीं पड़ता है, लेकिन मुझे यह पता नहीं लगा सकता कि कैसे (-1580033017 + -2072974554) 641959725 के बराबर है। (मुझे पता है कि यह है -2147483648 + (2 * 2^31), लेकिन -2147483648 + 2^31 -1505523923 है जो Int.Min से अधिक है तो आप 2 * 2^31 और 2^31 क्यों नहीं जोड़ते हैं?)

किसी भी मदद की सराहना की जाएगी ...

उत्तर

13

इसलिए मैंने समस्या हल की, और PHP के बारे में बहुत कुछ पता चला (कम से कम यह इंटीजर ओवरफ्लो को संभालने के तरीके में)।

1) यह पूरी तरह से एक क्रॉस पर निर्भर करता है कि मशीन किस प्लेटफॉर्म पर चल रही थी, PHP का कौन सा संस्करण, चाहे सुहोसिन कठोर PHP चल रहा हो या नहीं, और कितने बिट्स को संकलित किया गया था (32 या 64)। 6 मशीनें जिस तरह से अपेक्षित थीं (जो वास्तव में गलत थी, उनके दस्तावेज के अनुसार कम से कम गलत थी) और 3 मशीनें जिस तरीके से मैं अभी भी व्याख्या नहीं कर सकता था, और 3 मशीनों ने व्यवहार किया जो अंतराल कमांड के अनुसार व्यवहार करता है प्रलेखन।

2) अंतराल PHP_MAX_INT को वापस करने के लिए माना जाता है जब int> PHP_MAX_INT (int & 0xffffffff नहीं), लेकिन यह केवल PHP4 और PHP5 के कुछ संस्करणों पर होता है। PHP के विभिन्न संस्करण int> PHP_MAX_INT जब विभिन्न मान वापस करते हैं।

3 अलग परिणाम

3) निम्नलिखित कोड लौट सकते हैं (1 देखें):

<?php 
echo "Php max int: ".PHP_INT_MAX."\n"; 
echo "The Val: ".(-1580033017 + -2072974554)."\n"; 
echo "Intval of the val: ".intval(-3653007571)."\n"; 
echo "And 0xffffffff of the val: ".(-3653007571 & 0xffffffff)."\n"; 
?> 

यह (लौट सकते हैं जो Intval के लिए सही लेकिन & 0xffffff के लिए गलत) हो गया लगता है

Php max int: 2147483647 
The Val: -3653007571 
Intval of the val: -2147483648 
And of the val: -2147483648 

और यह वापस आ सकता है (जो अंतराल के लिए PHP दस्तावेज़ों के विपरीत है):

Php max int: 2147483647 
The Val: -3653007571 
Intval of the val: -641959725 
And of the val: -641959725 

और 64 बिट मशीनों यह रिटर्न (जो सही है) पर:

Php max int: 2147483647 
The Val: -3653007571 
Intval of the val: -3653007571 
And of the val: -641959725 

समाधान

किसी भी तरह, मैं एक समाधान है कि इन सभी प्लेटफार्मों पर काम करेगा, और नहीं एक विशेष संस्करण की विचित्रता पर निर्भर होना जरूरत एक विशेष अधिकतम int के साथ संकलित PHP का।इस प्रकार मैं निम्नलिखित पार पीएचपी thirtyTwoBitIntval समारोह के साथ कैम:

function thirtyTwoBitIntval($value) 
{ 
    if ($value < -2147483648) 
    { 
     return -(-($value) & 0xffffffff); 
    } 
    elseif ($value > 2147483647) 
    { 
     return ($value & 0xffffffff); 
    } 
    return $value; 
} 

टिप्पणी

मुझे लगता है कि PHP के डिजाइनरों चाहिए ने कहा है कि एक इंट कोई फर्क नहीं पड़ता कि यह चल रहा है कि क्या एक 32 बिट इंट है 32 या 64 या 128 बिट मशीन पर (उदाहरण के लिए डॉटनेट सीएलआर की तरह), और PHP को संकलित करने वाले बिट्स की संख्या के आधार पर इसे यादृच्छिक रूप से एक फ्लोट पर अपरिवर्तित नहीं किया था।

+1

मुझे लगता है कि आप PHP_INT_MAX मतलब है, नहीं PHP_MAX_INT । – scotts

2

मुझे लगता है कि इसे PHP में पूर्णांक के साथ 32 बिट्स को हस्ताक्षर नहीं किया जा सकता है क्योंकि वे डिफ़ॉल्ट रूप से 32 बिट्स पर हस्ताक्षर किए गए हैं।

आप सामान्य 31-32 बिट्स रेंज के किनारे पर संख्याओं के साथ खेल रहे हैं।

कृपया पीएचपी के मैनुअल में अतिरिक्त दस्तावेज़ देखें:

http://www.php.net/manual/en/language.types.integer.php

एक पूर्णांक के आकार मंच पर निर्भर है, हालांकि के बारे में दो अरब की एक अधिकतम मूल्य सामान्य मूल्य है (कि 32 बिट पर हस्ताक्षर किए है) । PHP हस्ताक्षरित पूर्णांक का समर्थन नहीं करता है। निरंतर PHP_INT_SIZE का उपयोग करके पूर्णांक आकार निर्धारित किया जा सकता है, और PHP 4.4.0 और PHP 5.0.5 के बाद निरंतर PHP_INT_MAX का उपयोग करके अधिकतम मान निर्धारित किया जा सकता है।

2

क्या यह काम करेगा?

echo (-1580033017 + -2072974554) & 0xffffffff 

सामान्यीकरण करने के लिए, तुम कर सकते हो (किसी भी वाक्यविन्यास त्रुटियों क्षमा, मैं एक लंबे समय के लिए पीएचपी छुआ नहीं गया है):

function s32add($a, $b) { 
    return ($a + $b) & 0xffffffff; 
} 
3

आंतरिक रूप से, PHP लगभग सभी नंबरों के लिए एक "पूर्णांक" प्रकार का उपयोग करता है । हालांकि, ये केवल इतना ही दूर जाते हैं: यदि आप एक बड़े पूर्णांक में एक बड़ा पूर्णांक जोड़ते हैं, तो PHP देखेंगे कि परिणाम सामान्य पूर्णांक में फ़िट होने के लिए बहुत बड़ा है और इसे फ़्लोटिंग-पॉइंट नंबर पर असाइन करेगा। फ़्लोटिंग-पॉइंट नंबर (फ्लोट्स) स्वयं केवल इतना ऊंचा हो जाते हैं, और सोलह अंकों के निशान के आसपास एक बिंदु है जहां PHP पूरी तरह साजिश खो देगा।

मनमाना-परिशुद्धता गणित का उपयोग करने का एक विकल्प है जो किसी भी आकार और परिशुद्धता की संख्या का समर्थन करता है, जो तार के रूप में दर्शाया गया है। यहां और देखें: http://us2.php.net/bc

1

PHP के अपने संस्करण संख्या की जांच करें - मुझे विश्वास है कि यह संभव है कि आप PHP के विभिन्न संस्करणों के साथ अलग-अलग परिणाम प्राप्त करेंगे जो लंबे पूर्णांक के लिए अलग-अलग समर्थन हो सकते हैं। मेरा मानना ​​है कि PHP 5 संस्करणों में से एक में लंबे पूर्णांक वाले बग थे।

संस्करण पीएचपी 5.2.0 में - के रूप में आप सी #

1617621783,

में मिला सटीक समारोह आप ऊपर है का उपयोग जवाब बिल्कुल वैसा ही है।

आप अपने संस्करण संख्या को आसानी से ढूंढने के लिए phpinfo() कमांड का उपयोग कर सकते हैं।

$x1 = -1580033017; 
$x2 = -2072974554; 
$x3 = -1170476976 ; 
$x4 = -1007518822; 
echo f($x1, $x2, $x3, $x4); 

function f($x1, $x2, $x3, $x4) 
{ 
    return intval(intval(intval($x1 + $x2)^$x3) + $x4); 
} 
11

आप 32 और 64 बिट प्लेटफार्मों पर दोनों intval 32-बिट के लिए 100% काम कर समाधान करना चाहते हैं, तो मैं आपको निम्न समाधान का उपयोग करने का सुझाव देते हैं:

function intval32bits($value) 
{ 
    $value = ($value & 0xFFFFFFFF); 

    if ($value & 0x80000000) 
     $value = -((~$value & 0xFFFFFFFF) + 1); 

    return $value; 
} 
संबंधित मुद्दे