বিটওয়াস শিফট এবং ব্যাশের বৃহত্তম সংখ্যক


16

এটি একটি অনুসন্ধানের প্রশ্ন, যার অর্থ আমি এই প্রশ্নটি কী তা সম্পর্কে পুরোপুরি নিশ্চিত নই, তবে আমি মনে করি এটি বাশের সবচেয়ে বড় পূর্ণসংখ্যা সম্পর্কে। যাইহোক, আমি এটি জোরালোভাবে সংজ্ঞায়িত করব।

$ echo $((1<<8))
256

আমি কিছুটা স্থানান্তরিত করে একটি পূর্ণসংখ্যা তৈরি করছি। আমি কতদূর যেতে পারি?

$ echo $((1<<80000))
1

আপাতদৃষ্টিতে এটি নয়। (1 অপ্রত্যাশিত, এবং আমি এটিতে ফিরে আসব)) তবে,

$ echo $((1<<1022))
4611686018427387904

এখনও ইতিবাচক। এটি অবশ্য নয়:

$ echo $((1<<1023))
-9223372036854775808

এবং আরও এক ধাপ এগিয়ে,

$ echo $((1<<1024))
1

কেন 1? এবং নিম্নলিখিত কেন?

$ echo $((1<<1025))
2
$ echo $((1<<1026))
4

কেউ কি এই সিরিজটি বিশ্লেষণ করতে চান?

হালনাগাদ

আমার যন্ত্র:

$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

-9223372036854775808 = 0xF333333333333334। এটি একটি মজার চেহারার প্রান্তের কেস। অবশ্যই, 4611686018427387904 = 0x4000000000000000। আমি সন্দেহ করি যে আপনি বিটগুলি স্থানান্তরিত করার জন্য কোনও ধরণের রেপরোয়ানা মারছেন। আপনি কেন এইভাবে করছেন?
একটি সিভিএন

6
@ মাইকেলKjörling বিনোদনের জন্য ;

2
@ মাইকেলKjörling না, না। -9223372036854775808 0x8000000000000000 হবে। আপনি চেক করার সময় চূড়ান্ত অঙ্কটি রেখে গেছেন: -922337203685477580 হবে 0xF33333333333333334।
এইচডিভি

উত্তর:


27

ব্যাশ ব্যবহার intmax_tগাণিতিক জন্য ভেরিয়েবল । আপনার সিস্টেমে এগুলির দৈর্ঘ্য 64 বিট, তাই:

$ echo $((1<<62))
4611686018427387904

যা হলো

100000000000000000000000000000000000000000000000000000000000000

বাইনারি (1 এর পরে 62 0s)। আবার শিফট করুন:

$ echo $((1<<63))
-9223372036854775808

যা হলো

1000000000000000000000000000000000000000000000000000000000000000

বাইনারি (63 0 সে), দুটির পরিপূরক গাণিতিকগুলিতে।

বৃহত্তম প্রতিনিধিত্বযোগ্য পূর্ণসংখ্যা পেতে আপনার 1 টি বিয়োগ করতে হবে:

$ echo $(((1<<63)-1))
9223372036854775807

যা হলো

111111111111111111111111111111111111111111111111111111111111111

বাইনারি মধ্যে

মধ্যে সরু আউট হিসাবে ilkkachu এর উত্তর , নাড়াচাড়া লাগে 64-বিট উপর মডিউল 64 অফসেট এক্স 86 সিপিইউ (ব্যবহার কিনা RCLবা SHL, যা আপনি ব্যবহার করছি দেখা ব্যাখ্যা):

$ echo $((1<<64))
1

সমতূল্য $((1<<0))। এভাবে $((1<<1025))হয় $((1<<1)), $((1<<1026))হয় $((1<<2))...

আপনি টাইপ সংজ্ঞা এবং সর্বাধিক মান খুঁজে পাবেন stdint.h; আপনার সিস্টেমে:

/* Largest integral types.  */
#if __WORDSIZE == 64
typedef long int                intmax_t;
typedef unsigned long int       uintmax_t;
#else
__extension__
typedef long long int           intmax_t;
__extension__
typedef unsigned long long int  uintmax_t;
#endif

/* Minimum for largest signed integral type.  */
# define INTMAX_MIN             (-__INT64_C(9223372036854775807)-1)
/* Maximum for largest signed integral type.  */
# define INTMAX_MAX             (__INT64_C(9223372036854775807))

1
না, আপনার তাদের দরকার, বাইনারি -এর চেয়ে বেশি অগ্রাধিকার রয়েছে <<
cuonglm

1
@ কুওগলম হু, জেডএসে পরীক্ষা করার জন্য আমাকে সঠিকভাবে সেবা করছে ... আবারও ধন্যবাদ!
স্টিফেন কিট

@ কুওগলম এবং স্টিফেন ঠিক আছে, এটি একটি ভাল সম্পাদনা। echo $((1<<63-1))আমাকে দেয় 4611686018427387904

টমাস ইয়ুপ, ব্যাশ সি অপারেটর অগ্রাধিকার ব্যবহার করে, zsh এর নিজস্ব পূর্বনির্ধারিত যেখানে $((1<<63-1))সমান $(((1<<63)-1))
স্টিফেন কিট

এটি জেনে রাখা ভাল, একটি ভাল প্রশ্ন এবং খুব জোরালো উত্তর, আপনাকে উভয়ই স্টিফেন কিট এবং টমাসকে ধন্যবাদ।
ভ্যালেন্টিন বি

4

2.05b এর CHANGESজন্য ফাইল থেকে bash:

ঞ। শেলটি এখন লম্বার পরিবর্তে মেশিনটি সমর্থন করে বৃহত্তম ইন্টিজার সাইজে (ইন্টম্যাক্স_টি) গণিত সম্পাদন করে।

X86_64 মেশিনে intmax_tস্বাক্ষরিত 64-বিট পূর্ণসংখ্যার সাথে সম্পর্কিত। সুতরাং আপনি -2^63এবং এর মধ্যে অর্থবোধক মান পাবেন 2^63-1। এই ব্যাপ্তির বাইরে আপনি কেবল মোড়কের কাছাকাছি পান।


নিতপিক: সমেত -2^63এবং 2^63-1অন্তর্ভুক্ত।
নামমাত্র প্রাণী

4

কারণ শিফট পরিমাণ কার্যকরভাবে, বিট (64) সংখ্যা মডিউল নেওয়া হয়, যাতে 1024 দ্বারা নাড়াচাড়া, একটি এক দেয় 1024 === 64 === 0, এবং 1025 === 65 === 1

কিছু বাদ দিয়ে অন্য কিছু স্থানান্তর করা 1এটিকে পরিষ্কার করে দেয় যে এটি কিছুটা আবর্তন নয়, কারণ উচ্চতর বিটগুলি শিফ্টের মান (কমপক্ষে) is৪ হওয়ার আগে নিম্ন প্রান্তে প্রায় আবদ্ধ হয় না:

$ printf "%x\n" $(( 5 << 63 )) $(( 5 << 64 ))
8000000000000000
5

এটি হতে পারে যে এই আচরণটি সিস্টেমের উপর নির্ভর করে। ব্যাশ কোড স্টিফেন লিঙ্ক শো ডান হাত মান কোন পরীক্ষণ ছাড়া শুধু একটি প্লেইন শিফট। যদি আমি সঠিকভাবে মনে রাখি, x86 প্রসেসর কেবল শিফ্ট মানের নীচে ছয় বিট ব্যবহার করে (-৪-বিট মোডে), তাই আচরণটি সরাসরি মেশিনের ভাষা থেকে হতে পারে। এছাড়াও, আমি মনে করি বিট প্রস্থের চেয়ে বেশি দ্বারা স্থানান্তরগুলি সি-তে পরিষ্কারভাবে সংজ্ঞায়িত করা হয়নি (এর gccজন্য সতর্ক করে দেয়)।


2

কিছুটা স্থানান্তরিত করে পূর্ণসংখ্যা উত্পাদন করা। আমি কতদূর যেতে পারি?

পূর্ণসংখ্যার প্রতিনিধিত্ব প্রায় মোড়ানো না হওয়া পর্যন্ত (বেশিরভাগ শেলের মধ্যে ডিফল্ট)।
একটি 64 বিট পূর্ণসংখ্যার প্রায় কাছাকাছি মোড়ানো 2**63 - 1
এটা 0x7fffffffffffffffবা 9223372036854775807ডিসেম্বরে।

এই সংখ্যাটি '+1' নেতিবাচক হয়ে যায়।

এটি যেমন 1<<63, একইভাবে :

$ echo "$((1<<62)) $((1<<63)) and $((1<<64))"
4611686018427387904 -9223372036854775808 and 1

এরপরে প্রক্রিয়াটি আবার পুনরাবৃত্তি করে।

$((1<<80000)) $((1<<1022)) $((1<<1023)) $((1<<1024)) $((1<<1025)) $((1<<1026))

ফলাফলটি mod 64স্থানান্তর মানটির উপর নির্ভর করে [এ]

[এ] থেকে: ইন্টেল ®৪ এবং আইএ -32 আর্কিটেকচার সফটওয়্যার বিকাশকারীর ম্যানুয়াল: খণ্ড 2 গণনাটি 5 বিটগুলিতে মাস্ক করা হয়েছে (বা b বিট যদি bit৪-বিট মোডে থাকে এবং আরএক্স.ডাব্লু ব্যবহৃত হয়)। গণনা পরিসীমা 0 থেকে 31 (বা 63--বিট মোড এবং REX.W ব্যবহৃত হলে 63) এর মধ্যে সীমাবদ্ধ।

এছাড়াও: মনে রাখবেন যে $((1<<0))হয়1

$ for i in 80000 1022 1023 1024 1025 1026; do echo "$((i%64)) $((1<<i))"; done
 0 1
62 4611686018427387904
63 -9223372036854775808
 0 1
 1 2
 2 4

সুতরাং, এটি সমস্ত 64 এর একাধিক সংখ্যার কতটা কাছাকাছি তার উপর নির্ভর করে।

সীমা পরীক্ষা করা:

সর্বাধিক ধনাত্মক (এবং negativeণাত্মক) পূর্ণসংখ্যার যা পরীক্ষা করার শক্তিশালী উপায় হ'ল প্রতিটি এক এক করে বিট পরীক্ষা করা। এটি বেশিরভাগ কম্পিউটারের জন্য 64৪ টিরও কম পদক্ষেপ, এটি খুব ধীর হবে না।

সজোরে আঘাত

প্রথমে আমাদের ফর্মের বৃহত্তম 2^nসংখ্যার প্রয়োজন (জিরো অনুসারে 1 বিট সেট)। পরবর্তী শিফটটি সংখ্যাটিকে নেতিবাচক না করা পর্যন্ত বাম দিকে নাড়াচাড়া করে আমরা এটি করতে পারি , এটি "আশেপাশে মোড়ানো "ও বলে:

a=1;   while ((a>0));  do ((b=a,a<<=1))  ; done

bফলাফলটি কোথায় : শেষ শিফটের আগে মানটি যা লুপকে ব্যর্থ করে।

তারপরে কোনটি সাইনকে প্রভাবিত করে তা খুঁজে বের করার জন্য আমাদের প্রতিটি চেষ্টা করতে হবে e:

c=$b;d=$b;
while ((c>>=1)); do
      ((e=d+c))
      (( e>0 )) && ((d=e))
done;
intmax=$d

সর্বাধিক পূর্ণসংখ্যা ( intmax) এর শেষ মান থেকে ফলাফল d

নেতিবাচক দিকে (এর চেয়ে কম 0) আমরা সমস্ত পরীক্ষার পুনরাবৃত্তি করি তবে পরীক্ষা করে নিই যখন কিছুটা মোড়ানো না করে কিছুটা 0 করা যায়।

সমস্ত পদক্ষেপের মুদ্রণের সাথে একটি সম্পূর্ণ পরীক্ষাটি হ'ল (বাশের জন্য):

#!/bin/bash
sayit(){ printf '%020d 0x%016x\n' "$1"{,}; }
a=1;       while ((a>0)) ; do((b=a,a<<=1))              ; sayit "$a"; done
c=$b;d=$b; while((c>>=1)); do((e=d+c));((e>0))&&((d=e)) ; sayit "$d"; done;
intmax=$d
a=-1;      while ((a<0)) ; do((b=a,a<<=1))              ; sayit "$b"; done;
c=$b;d=$b; while ((c<-1)); do((c>>=1,e=d+c));((e<0))&&((d=e)); sayit "$d"; done
intmin=$d       

printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"

SH

প্রায় কোনও শেল অনুবাদিত:

#!/bin/sh
printing=false
sayit(){ "$printing" && printf '%020d 0x%016x\n' "$1" "$1"; }
a=1;       while [ "$a" -gt 0  ];do b=$a;a=$((a<<1)); sayit "$a"; done
c=$b;d=$b; while c=$((c>>1)); [ "$c" -gt 0 ];do e=$((d+c)); [ "$e" -gt 0 ] && d=$e ; sayit "$d"; done;
intmax=$d
a=-1;      while [ "$a" -lt 0  ];do b=$a;a=$((a<<1)); sayit "$b"; done;
c=$b;d=$b; while [ "$c" -lt -1 ];do c=$((c>>1));e=$((d+c));[ "$e" -lt 0 ] && d=$e ; sayit "$d"; done
intmin=$d       

printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"

অনেকগুলি শেলের জন্য
উপরেরটি চালানো, সমস্ত (ব্যাশ 2.04 এবং mksh ব্যতীত 2**63 -1) এই কম্পিউটারে ( ) অবধি মান গ্রহণযোগ্য ।

এটি আকর্ষণীয় যে এটিটি শেল :

$ attsh --version
version         sh (AT&T Research) 93u+ 2012-08-01

এর মানগুলিতে একটি ত্রুটি মুদ্রিত হয়েছে $((2^63)), যদিও ksh নয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.