स्विफ्ट भाषा में कुछ इंटिजर की शक्ति कैसे प्राप्त करें?


102

मैं हाल ही में तेजी से सीख रहा हूं, लेकिन मुझे एक बुनियादी समस्या है जिसका जवाब नहीं मिल रहा है

मैं कुछ ऐसा हासिल करना चाहता हूं

var a:Int = 3
var b:Int = 3 
println( pow(a,b) ) // 27

लेकिन पॉव फ़ंक्शन केवल डबल संख्या के साथ काम कर सकता है, यह पूर्णांक के साथ काम नहीं करता है, और मैं डबल (ए) या a.double () ...

यह पूर्णांक की शक्ति की आपूर्ति क्यों नहीं करता है? यह निश्चित रूप से अस्पष्टता के बिना एक पूर्णांक लौटाएगा! और मैं एक पूर्णांक को दोहरे में क्यों नहीं डाल सकता हूं? यह सिर्फ 3 से 3.0 में बदल (या 3.00000 ... जो भी)

अगर मुझे दो पूर्णांक मिला है और मैं शक्ति संचालन करना चाहता हूं, तो मैं इसे सुचारू रूप से कैसे कर सकता हूं?

धन्यवाद!


इस प्रकार की घोषणाएं गलत हैं
एडगर अरौटियूनियन

अधिकांश भाषाओं में इस कारण
phuclv

1
@ phuclv के नोट विषय पर एक महान चर्चा की ओर इशारा करते हैं। मैं "इन कारणों" के लिंक में पाठ को बदल
दूंगा

जवाबों:


78

यदि आप चाहें, तो आप infix operatorइसे करने की घोषणा कर सकते हैं ।

// Put this at file level anywhere in your project
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
    return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i = 2 ^^ 3
// ... or
println("2³ = \(2 ^^ 3)") // Prints 2³ = 8

मैंने दो कैरेट का उपयोग किया ताकि आप अभी भी XOR ऑपरेटर का उपयोग कर सकें ।

स्विफ्ट 3 के लिए अपडेट

स्विफ्ट 3 में "मैजिक नंबर" precedenceद्वारा प्रतिस्थापित किया गया है precedencegroups:

precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
func ^^ (radix: Int, power: Int) -> Int {
    return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i2 = 2 ^^ 3
// ... or
print("2³ = \(2 ^^ 3)") // Prints 2³ = 8

इसलिए यदि आप फ्लोट्स के लिए ऐसा करना चाहते हैं, तो क्या आप ऐसा करेंगे: infix ऑपरेटर ^ ^ {} func ^^ (मूलांक: फ्लोट, पावर: फ्लोट) -> फ्लोट {रिटर्न फ्लोट (पाओ (डबल (रेडिक्स)), डबल (पावर) )))}
पैडपा

func ^ ^ (मूलांक: डबल, पावर: डबल) -> डबल {रिटर्न डबल (पॉव (डबल (मूलांक)), डबल (पावर))}
पैडपा

3
मैंने पाया कि जैसा मैंने अपेक्षित किया था वैसा व्यवहार नहीं किया क्योंकि पूर्ववर्तीता बंद थी। एक घातांक ऑपरेटर के लिए, 160 से पहले की स्थिति निर्धारित करें ( जैसे developer.apple.com/library/ios/documentation/Swift/Conceptual/… और developer.apple.com/library/ios/documentation/Sonift/Conceptual/… ) को इस तरह देखें : infix operator ^^ { precedence 160 } func ^^... और इसी तरह
टिम काम्बर

मैं वास्तव में इस समाधान को पसंद करता हूं, लेकिन स्विफ्ट 3 के साथ यह काम नहीं करता है। किसी भी विचार यह कैसे काम करने के लिए?
वान्या

1
func p(_ b: Bool) -> Double { return b?-1:1 }?
ग्रिम्क्सन

59

इसके अलावा आपके परिवर्तनशील घोषणाओं में वाक्यविन्यास त्रुटियां हैं, यह ठीक उसी तरह काम करता है जैसा आपने उससे अपेक्षा की थी। आपको बस इतना करना है aऔर bमूल्यों को डबल और पास करना है pow। फिर, यदि आप 2 Ints के साथ काम कर रहे हैं और आप ऑपरेशन के दूसरी तरफ एक Int चाहते हैं, तो Int को वापस कास्ट करें।

import Darwin 

let a: Int = 3
let b: Int = 3

let x: Int = Int(pow(Double(a),Double(b)))

यह उत्तर डबल और इंट प्रकार के साथ सबसे स्पष्ट है।
मिडटाउनगुरु

यही मैं चाहता हूं, धन्यवाद। पायथन में, बस 3 ** 3। कभी-कभी, मुझे स्विफ्ट का उपयोग करके एल्गोरिथ्म समस्या को हल करने की आवश्यकता होती है, यह पायथन के उपयोग की तुलना में वास्तव में दर्दनाक है।
चाकझौब

13

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

Double(Int.max - 1) < Double(Int.max) // false!

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

// using Swift 5.0
func pow<T: BinaryInteger>(_ base: T, _ power: T) -> T {
    func expBySq(_ y: T, _ x: T, _ n: T) -> T {
        precondition(n >= 0)
        if n == 0 {
            return y
        } else if n == 1 {
            return y * x
        } else if n.isMultiple(of: 2) {
            return expBySq(y, x * x, n / 2)
        } else { // n is odd
            return expBySq(y * x, x * x, (n - 1) / 2)
        }
    }

    return expBySq(1, base, power) 
}

नोट: इस उदाहरण में मैंने एक सामान्य प्रयोग किया है T: BinaryInteger। ऐसा इसलिए है कि आप किसी अन्य पूर्णांक-प्रकार का उपयोग कर सकते हैं Intया कर सकते हैं UInt


और निश्चित रूप से आप इसे हमेशा एक ऑपरेटर के रूप में परिभाषित कर सकते हैं (जैसा कि अधिक लोकप्रिय उत्तर सुझाते हैं) Intया आप के लिए एक विस्तार हो सकता है या आप उन चीजों को इस मुफ्त फ़ंक्शन को कॉल कर सकते हैं - जो भी आपके दिल की इच्छा है।
mklbtz

ऐसा लगता है, यह समाधान एक स्टैकओवरफ़्लो अपवाद की ओर जाता है
व्यस्कलेव

11

यदि आप वास्तव में 'केवल इंट' लागू करना चाहते हैं और इसके लिए कोई जबरदस्ती नहीं चाहते हैंDouble , तो आपको इसे लागू करने की आवश्यकता होगी। यहां एक तुच्छ कार्यान्वयन है; तेजी से एल्गोरिदम हैं, लेकिन यह काम करेगा:

func pow (_ base:Int, _ power:UInt) -> Int {
  var answer : Int = 1
  for _ in 0..<power { answer *= base }
  return answer
}

> pow (2, 4)
$R3: Int = 16
> pow (2, 8)
$R4: Int = 256
> pow (3,3)
$R5: Int = 27

वास्तविक कार्यान्वयन में आप शायद कुछ त्रुटि की जाँच करना चाहते हैं।


यह पूरी तरह से मान्य उत्तर है। ऐसे कुछ उदाहरण हैं जहां Ints को Doubles में परिवर्तित करना सटीक खो देता है, और इसलिए यह Int pow के लिए एक व्यवहार्य समाधान नहीं है। बस Double(Int.max - 1) < Double(Int.max)एक स्विफ्ट 3 REPL में चलाने की कोशिश करें और आप आश्चर्यचकित हो सकते हैं।
mklbtz

2
इसे छोटा करने के लिए, आप इसे reduceकॉल के साथ लागू कर सकते हैं। return (2...power).reduce(base) { result, _ in result * base }
mklbtz

1
शायद आप
hashemi


4

यदि आपको ऑपरेटर ओवरलोडिंग की ओर डिस्क्राइब किया गया है (हालांकि ^^समाधान शायद आपके कोड को पढ़ने वाले किसी व्यक्ति के लिए स्पष्ट है) तो आप त्वरित कार्यान्वयन कर सकते हैं:

let pwrInt:(Int,Int)->Int = { a,b in return Int(pow(Double(a),Double(b))) }
pwrInt(3,4) // 81

4

mklbtz पूर्णांक शक्तियों की गणना के लिए मानक एल्गोरिथ्म होने के कारण घातांक के बारे में सही है, लेकिन एल्गोरिथ्म की पूंछ-पुनरावर्ती कार्यान्वयन थोड़ा भ्रामक लगता है। सी में स्क्वेरिंग द्वारा एक्सप्रेशन के गैर-पुनरावर्ती कार्यान्वयन के लिए http://www.programminglogic.com/fast-exponentiation-algorithms/ देखें । मैंने इसे यहां स्विफ्ट करने के लिए अनुवाद करने का प्रयास किया है:

func expo(_ base: Int, _ power: Int) -> Int {
    var result = 1

    while (power != 0){
        if (power%2 == 1){
            result *= base
        }
        power /= 2
        base *= base
    }
    return result
}

बेशक, यह एक अतिभारित ऑपरेटर को कॉल करने के लिए बनाकर कट्टर हो सकता है और इसे फिर से अधिक सामान्य बनाने के लिए लिखा जा सकता है इसलिए इसने IntegerTypeप्रोटोकॉल को लागू करने वाली किसी भी चीज पर काम किया । इसे सामान्य बनाने के लिए, मैं शायद कुछ के साथ शुरू करूँगा

    func expo<T:IntegerType>(_ base: T, _ power: T) -> T {
    var result : T = 1

लेकिन, यह संभवत: दूर किया जा रहा है।


1
बहुत अच्छा! Swift> 4.0 (Xcode 9.0) में यह उदारतापूर्वक करने के लिए, आप उपयोग करना चाहते हैं BinaryIntegerIntegerTypeपदावनत कर दिया गया।
मलबतज़


3

कुछ अतिरिक्त भाषाओं के उपयोग के जवाबों को एक अतिरिक्त कार्य में सेट करना (और "**" के बजाय "**" का उपयोग करना - जैसा कि मेरे लिए स्पष्ट है):

// http://stackoverflow.com/questions/24196689/how-to-get-the-power-of-some-integer-in-swift-language
// Put this at file level anywhere in your project
infix operator ** { associativity left precedence 160 }
func ** (radix: Double, power: Double) -> Double { return pow(radix, power) }
func ** (radix: Int,    power: Int   ) -> Double { return pow(Double(radix), Double(power)) }
func ** (radix: Float,  power: Float ) -> Double { return pow(Double(radix), Double(power)) }

फ्लोट का उपयोग करते समय, आप सटीक खो सकते हैं। यदि संख्यात्मक शाब्दिक और पूर्णांक और गैर-पूर्णांकों के मिश्रण का उपयोग कर रहे हैं, तो आप डिफ़ॉल्ट रूप से डबल के साथ समाप्त हो जाएंगे। मैं व्यक्तिगत रूप से शैलीगत / पठनीयता कारणों के लिए पाउ (ए, बी) जैसे फ़ंक्शन के बजाय गणितीय अभिव्यक्ति का उपयोग करने की क्षमता पसंद करता हूं, लेकिन यह सिर्फ मेरे लिए है।

कोई भी ऑपरेटर जो त्रुटि उत्पन्न करने के लिए pow () का कारण बनेगा, इन कार्यों के कारण भी त्रुटि होगी, इसलिए त्रुटि जाँच का भार अभी भी पावर फ़ंक्शन का उपयोग करके कोड के साथ निहित है। KISS, IMHO।

देशी पाव () फ़ंक्शन का उपयोग करके उदाहरण के लिए वर्गमूल (2 ** 0.5) या व्युत्क्रम (2 ** -3 = 1/8) लेने की अनुमति देता है। उलटा या भिन्नात्मक घातांक का उपयोग करने की संभावना के कारण, मैंने अपने सभी कोड को डिफ़ॉल्ट डबल प्रकार के पाव () फ़ंक्शन को वापस करने के लिए लिखा था, जिसे सबसे अधिक सटीक (यदि मुझे सही ढंग से दस्तावेज याद है) वापस करना चाहिए। यदि आवश्यक हो, तो यह इंट या फ्लोट के लिए टाइप-कास्ट किया जा सकता है या जो भी हो, संभवतः परिशुद्धता के नुकसान के साथ।

2 ** -3  = 0.125
2 ** 0.5 = 1.4142135623731
2 ** 3   = 8

pow () बड़ी गणना के लिए उपयुक्त नहीं है, जहां भिन्नात्मक भाग भी बहुत महत्वपूर्ण है। मेरे लिए आपका जवाब एक संकेत देता है। धन्यवाद :)
महेंद्र

3

यह पता चला है कि आप भी उपयोग कर सकते हैं pow()। उदाहरण के लिए, आप 10 से 9 वें व्यक्त करने के लिए निम्नलिखित का उपयोग कर सकते हैं।

pow(10, 9)

साथ में pow, powf()एक के floatबजाय रिटर्न देता है double। मैंने केवल स्विफ्ट 4 और मैकओएस 10.13 पर इसका परीक्षण किया है।


1
pow (ए, बी) NaN लौटाता है अगर b <0; तो आप इसके लिए एक परीक्षण जोड़ सकते हैं: शक्ति = (b> = 0) दें? pow (a, b): 1 / pow (a -b); ध्यान दें कि दशमलव घोषित किया जाना चाहिए: दशमलव = 2;
Let


1

स्विफ्ट 4.x संस्करण

precedencegroup ExponentiationPrecedence {
  associativity: right
  higherThan: MultiplicationPrecedence
}

infix operator ^^: ExponentiationPrecedence
public func ^^ (radix: Float, power: Float) -> Float {
  return pow((radix), (power))
}

public func ^^ (radix: Double, power: Double) -> Double {
  return pow((radix), (power))
}

public func ^^ (radix: Int, power: Int) -> Int {
  return NSDecimalNumber(decimal: pow(Decimal(radix), power)).intValue
}

1

स्विफ्ट 5 में:

extension Int{
    func expo(_ power: Int) -> Int {
        var result = 1
        var powerNum = power
        var tempExpo = self
        while (powerNum != 0){
        if (powerNum%2 == 1){
            result *= tempExpo
        }
        powerNum /= 2
        tempExpo *= tempExpo
        }
        return result
    }
}

इस तरह का उपयोग करें

2.expo(5) // pow(2, 5)

@Paul Buis के उत्तर के लिए धन्यवाद।



1

एक इंट-बेस्ड पॉव फंक्शन, जो स्विफ्ट 5 में बेस 2 के लिए बिट शिफ्ट के जरिए सीधे वैल्यू की गणना करता है:

func pow(base: Int, power: UInt) -> Int {
    if power == 0 { return 1 }
    // for base 2, use a bit shift to compute the value directly
    if base == 2 { return 2 << Int(power - 1) }
    // otherwise multiply base repeatedly to compute the value
    return repeatElement(base, count: Int(power)).reduce(1, *)
}

(सुनिश्चित करें कि परिणाम इंट की सीमा के भीतर है - यह सीमा मामले से बाहर की जाँच नहीं करता है)


1

अन्य उत्तर बहुत अच्छे हैं, लेकिन अगर पसंद किया जाता है, तो आप इसे Intविस्तार के साथ भी कर सकते हैं, जब तक कि एक्सपोजर सकारात्मक है।

extension Int {   
    func pow(toPower: Int) -> Int {
        guard toPower > 0 else { return 0 }
        return Array(repeating: self, count: toPower).reduce(1, *)
    }
}

2.pow(toPower: 8) // returns 256

0

ओवरलोडिंग को संयोजित करने की कोशिश करते हुए, मैंने जेनरिक का उपयोग करने की कोशिश की, लेकिन यह काम नहीं कर सका। मैं अंततः अधिभार या जेनरिक का उपयोग करने के बजाय NSNumber का उपयोग करने के लिए लगा। यह निम्नलिखित को सरल करता है:

typealias Dbl = Double // Shorter form
infix operator ** {associativity left precedence 160}
func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {return pow(Dbl(lhs), Dbl(rhs))}

निम्न कोड ऊपर के रूप में एक ही फ़ंक्शन है, लेकिन यह देखने के लिए कि क्या पैरामीटर को डबल्स में सफलतापूर्वक परिवर्तित किया जा सकता है, त्रुटि जाँच करता है।

func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {
    // Added (probably unnecessary) check that the numbers converted to Doubles
    if (Dbl(lhs) ?? Dbl.NaN) != Dbl.NaN && (Dbl(rhs) ?? Dbl.NaN) != Dbl.NaN {
        return pow(Dbl(lhs), Dbl(rhs))
    } else {
        return Double.NaN
    }
}

-1

स्विफ्ट 5

मैं हैरान था, लेकिन मुझे यहां एक सही सही समाधान नहीं मिला।

यह मेरा है:

enum CustomMath<T: BinaryInteger> {

    static func pow(_ base: T, _ power: T) -> T {
        var tempBase = base
        var tempPower = power
        var result: T = 1

        while (power != 0) {
            if (power % 2 == 1) {
                result *= base
            }
            tempPower = tempPower >> 1
            tempBase *= tempBase
        }
        return result
    }
}

उदाहरण:

CustomMath.pow(1,1)

-2

मुझे यह बेहतर लगता है

func ^ (left:NSNumber, right: NSNumber) -> NSNumber {
    return pow(left.doubleValue,right.doubleValue)
}
var a:NSNumber = 3
var b:NSNumber = 3 
println( a^b ) // 27

3
जो मानक xor ऑपरेटर को प्रतिस्थापित करता है। इसका उपयोग करने से आपका कोड किसी ऐसे व्यक्ति के साथ बहुत ही अनपेक्षित तरीके से व्यवहार करेगा, जो यह नहीं जानता है कि आप सिंगल कैरेट को ओवरराइड कर रहे हैं।
wjl 20

-3
func calc (base:Int, number:Int) -> Int {
    var answer : Int = base
    for _ in 2...number {answer *= base } 
    return answer
}

उदाहरण:

calc (2,2)

1
यह समझाने के लिए अच्छा अभ्यास है कि आपका कोड एक उत्तर में सिर्फ डंपिंग कोड के बजाय एक समाधान क्यों प्रदान करता है।
रूडी केरशव

1
और यह एक सही पावर फंक्शन से दूर है। एक्सपोनेंट या किसी भी नकारात्मक मूल्य के रूप में 0 के बारे में क्या।
मैकबर्डी

इसके अलावा, नाम 'कैल्क' भी इस तरह के एक विशिष्ट ऑपरेशन में उपयोग किए जाने के लिए बहुत सामान्य है। कैल (2,2) का मतलब किसी भी संभावित गणना से हो सकता है जिसे आप 2 नंबर पर लागू करना चाहते हैं ... 2 + 2, 2-2, 2 * 2, 2/2, 2pow2, 2root2, आदि
eharo2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.