नीचे तीन कार्य हैं, प्रत्येक एक ही काम करता है लेकिन थोड़ा अलग तरीके से करता है। वे सभी संख्याओं को सरणी में गुणा करते हैं और परिणाम लौटाते हैं। लेकिन एक अजीब व्यवहार है क्या कोई कृपया बता सकता है कि क्या अंतर है।

function _mreduce0(name) {
  return name.split('').reduce((acc, e) => {
    return acc * 31 * e.charCodeAt(0);
  }, 7);
}

function _mreduce1(name) {
  let nArr = name.split('');
  let acc = 7;
  for (let i = 0; i < nArr.length; i += 1) {
    acc *= 31 * nArr[i].charCodeAt(0);
  }
  return acc;
}

function _mreduce2(name) {
  let nArr = name.split('');
  let acc = 7;
  for (let i = 0; i < nArr.length; i += 1) {
    acc = acc * 31 * nArr[i].charCodeAt(0);
  }
  return acc;
}

let n = 'somename';

console.log(_mreduce0(n) === _mreduce1(n)); // true
console.log(_mreduce0(n) === _mreduce2(n)); // true


// It is good for small size but when the string is large there is difference.
n = 'e868831414410da6b0b416be7e80f5211765ad4d1aed295cd24fcc17e72c03fc';

console.log(_mreduce0(n) === _mreduce1(n)); // false
console.log(_mreduce0(n) === _mreduce2(n)); // true
2
Muqsith 27 मार्च 2018, 15:14

2 जवाब

आम तौर पर गुणन सहयोगी होता है, लेकिन ऐसा लगता है कि जावास्क्रिप्ट इंजन एक मामले में a = a*b; a = a*c; करता है और दूसरे मामले में यह tmp = (b*c); a = a*tmp; करता है। दोनों ही मामलों में अंकगणितीय अतिप्रवाह होगा, लेकिन एक अलग तरीके से इसलिए वे अलग तरह से व्यवहार करते हैं।

नीचे एक अनुक्रम है जो समान प्रभाव दिखाता है। मतभेद होते हैं, जो तब स्वयं भी सुलझ जाते हैं, फिर से घटित होते हैं, आदि।

var x = 7;
var y = 7;

console.log(x === y);
for (var i = 1; i < 50; i++) {
  x *= 31 * 3;
  y = y * 31 * 3;
  console.log('i = ' + i + ' -> ' + (x === y ? "equal" : "diff: " + (x - y)));
}

अगर हम इसे y = y * 93 का उपयोग करने के लिए बदलते हैं तो कोई फर्क नहीं पड़ता:

var x = 7;
var y = 7;

console.log(x === y);
for (var i = 1; i < 50; i++) {
  x *= 31 * 3;
  y = y * 93;
  console.log('i = ' + i + ' -> ' + (x === y ? "equal" : "diff: " + (x - y)));
}

मेरा निष्कर्ष यह है कि y = y * 31 * 3 प्रत्येक * के बाद संभावित अंकगणितीय त्रुटि प्रभावों के साथ, बाएं से दाएं दाएं हाथ की गणना करता है।

y *= 31 * 3 वास्तव में ऐसा ही करता है, लेकिन यहां दायीं ओर हमेशा 31 * 3 === 93 होता है जिसे वह फिर y से गुणा करता है।

1
Peter B 28 मार्च 2018, 14:08

जावास्क्रिप्ट का केवल एक प्रकार है - संख्या - और संख्या हमेशा फ़्लोटिंग पॉइंट प्रकार होती है।

इसका क्या मतलब है? कि यह वास्तव में कुछ संख्या को छोड़ सकता है या बहुत बड़ी, बहुत कम या दशमलव संख्याओं के साथ गिनती के साथ सटीक परिणाम नहीं है।

"बहुत बड़ा" क्या है? यह मान है: https://developer .mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

यदि आप इस मान से अधिक हैं (और आप करते हैं), तो आप मूल जावास्क्रिप्ट संख्या का उपयोग नहीं कर सकते हैं (ठीक है आप कर सकते हैं, लेकिन आप ऐसे परिणाम प्राप्त कर सकते हैं जो सटीक नहीं हैं)

1
libik 27 मार्च 2018, 12:30