2009-01-26 5 views
6

मैं एक वर्ग है जो एक आकार का प्रतिनिधित्व करता है। आकार वर्ग में एंगल नामक एक संपत्ति है। मैं इस संपत्ति के लिए सेटर को स्वचालित रूप से सीमा [0,35 9] श्रेणी में लपेटना चाहता हूं।सी # में, मैं Google कैल्क की तरह मॉड्यूलस कैसे कार्यान्वित करूं?

दुर्भाग्यवश, एक साधारण _Angle = value % 360; केवल सकारात्मक संख्याओं के लिए काम करता है। सी #, -40 % 360 == -40 में। Google कैल्क यह the way I want it करता है। मान 320 होना चाहिए।

सी # में सबसे सुरुचिपूर्ण समाधान क्या है?

 public double Angle { 
     get { return _Angle; } 
     set { 
      if (value >= 0) { 
       _Angle = value % 360; 
      } 
      else { 
       _Angle = value - (360 * ((int)(value/360) - 1)); 
      } 
     } 
    } 

संपादित करें::

धन्यवाद दोस्तों, मैं अब है:

 public double Angle { 
     get { return _Angle; } 
     set { 
      _Angle = (value % 360) + ((value < 0) ? 360 : 0); 
     } 
    } 

..Which एक बहुत है

यहाँ सबसे अच्छा तरीका है मैं अब तक मिल गया है है बेहतर :)

+1

मैं मॉड्यूल ऑपरेशन के उपयोग को दृढ़ता से हतोत्साहित करता हूं क्योंकि हार्डवेयर मोड/विभाजन धीमा है। यदि आप दो की शक्ति होने के लिए अपने डेटा को स्केल करने में सक्षम हैं, तो आप एक बेहतर समाधान का उपयोग कर सकते हैं जो बिट मास्क का लाभ उठाता है। –

+0

@TrevorBoydmith: क्या सी # कंपाइलर को पूर्णांक के मामले में विभाजन और मॉड्यूलस को बिट ऑपरेशंस को अनुकूलित करने की अनुमति नहीं है? क्या आप फ़्लोटिंग वैल्यू के मामले में बिट ऑपरेशंस को अनुकूलित कर सकते हैं? –

उत्तर

9

हालांकि यह जावा के लिए है, जावा भी मॉड्यूलस के लिए एक ही व्यवहार है। (यानी -40 % 360 == -40)।

नीचे दिए गए कोड को [0 से जवाब देना चाहिए। 360), दिए गए कोण, सकारात्मक या नकारात्मक के बावजूद।

public class Mod 
{ 
    public static int mod(int a, int b) 
    { 
     if (a < 0) 
      return b + (a % b); 
     else 
      return a % b; 
    } 

    public static void main(String[] args) 
    { 
     System.out.println(mod(40, 360)); // 40 
     System.out.println(mod(-40, 360)); // 320 
     System.out.println(mod(-400, 360)); // 320 
    } 
} 

ध्यान दें कि दिए गए कोण को पिछले -360 के दौरान काम करता है।

+0

वाह यह बहुत जटिल है, आपको वास्तव में उस अतिरिक्त बयान की आवश्यकता नहीं है। –

+0

हां, ज़ाहिर है! मेरे कोड से बहुत आसान है। – Blorgbeard

1

// go 'round once

set { _Angle = (value + 360) % 360 }

+0

मैंने इसके बारे में सोचा, लेकिन क्या होगा यदि -360 से कम मूल्य पास हो गया है? – Blorgbeard

+0

हां, मैं यहां मान रहा हूं कि प्रत्येक अद्यतन पर कोण सामान्यीकृत है। –

-1
(360 * Math.floor(Math.abs(value)/360) + value) % 360 
-1

अपने मूल्यों बेतहाशा रेंज आप एक छोटे से पाश कर सकते हैं से बाहर होने के लिए नहीं जा रहे हैं।

while (value < 0) { 
    value = value + 360; 
} 
while (value > 360) { 
    value = value - 360; 
} 
3

यह आपको आवश्यक परिणाम

public double Angle { 
    get { return _Angle; } 
    set { _Angle = value % 360 + (value % 360 < 0 : 360 : 0); } 
} 

मैं यह सोचते हैं कि 360 डिग्री है और आप को खोजने के लिए जहां में {0, 360} कोण निहित है कोशिश कर रहे हैं देना चाहिए।

+1

(-1) यदि आप एक अनियंत्रित के लिए कोबर्ड को बेरेट करते हैं, और आपका कोड (गलत टाइप किया गया) उपयोग करता है?:। क्या आपको लगता है कि संकलक इसके लिए सशर्त उत्पन्न नहीं करता है? – RAL

+1

ठीक है (-1) आप पर वापस, यह नहीं है कि उसने आईएफ कथन का उपयोग कैसे किया, यह तथ्य था कि पोस्टर ने जो पूछा वह संतुष्ट नहीं था। उसके पास पहले से ही एक आईएफ कथन था, लेखक अपने कोड को कम करना चाहता था, इसमें एक आईएफ कथन के साथ एक और तरीका जोड़ना नहीं था –

+1

आपके पास वास्तव में अतिरिक्त '%' भी है - 'मान% 360' शून्य से कम है iff 'value' शून्य से कम है। – Blorgbeard

4

जबकि आपका समाधान समस्या के लिए काम करता है, जबकि आपके पास एल्गोरिदम वास्तव में Google द्वारा उपयोग किए जाने वाले किसी के समान नहीं है। यदि आप नकारात्मक divisor का उपयोग करते हैं तो यह अलग है।

public double GoogleModulo(double value, double divisor) 
{ 
    long q = (long)Math.Floor(value/divisor); 
    return value - q * divisor; 
} 

Console.WriteLine(GoogleModulo( 40, 360)); // 40 
Console.WriteLine(GoogleModulo(-40, 360)); // 320 
Console.WriteLine(GoogleModulo(-400, 360)); // 320 
Console.WriteLine(GoogleModulo( 40, -360)); // -320 

अंतिम गणना here पर Google की प्रतिक्रिया की जांच करें।

एल्गोरिदम wikipedia पर समझाया गया है और डोनाल्ड Knuth के लिए जिम्मेदार है।

2

मॉड ऑपरेशन बहुत धीमा है। यदि संभव हो तो बिट मास्क के साथ प्रतिस्थापित करें।

कोबर्ड का कोड बहुत अच्छा है ... लेकिन बहुत धीमा है क्योंकि यह एक मॉड ऑपरेशन कर रहा है। यदि यह दो रेंज में से कुछ शक्ति के भीतर होने के लिए अपने डेटा पैमाने पर करने के लिए संभव है, तो आप गति लगभग द्वारा (बहुत कम 2 या 3 गुना तेजी पर) परिमाण के एक आदेश थोड़ा मुखौटा का उपयोग करके सुधार कर सकते हैं।

सी कोड:

#define BIT_MASK (0xFFFF) 
if (a < 0) { 
    return b + (a & BIT_MASK); 
} else { 
    return a & BIT_MASK; 
} 

उस समय चलाया जाता है #define कुछ बनाने के लिए स्वतंत्र महसूस। और बिट मास्क को समायोजित करने के लिए स्वतंत्र महसूस करें जो आपको दो की जरूरत है। 0xFFFFFFFF या दो की शक्ति की तरह आप कार्यान्वयन पर निर्णय लेते हैं।

+0

जब तक कोण की सेटिंग CPU समय की एक बड़ी मात्रा ले रही है, मुझे लगता है कि प्रयास के लायक नहीं है। मेरा वर्तमान कंप्यूटर 2 धागे का उपयोग करके छोटे कोणों के लिए 450 मिलन मॉड्यूलस संचालन कर सकता है। बिट ऑपरेशंस का उपयोग 2.5-3 गुना तेज था। 1 मिलियन परिचालन में यह केवल 1.5 मिलीसेकंड बचाता है। – ggf31416

+0

यदि 2 से 3 एक्स प्रदर्शन वृद्धि 'अच्छा' नहीं है, तो आपकी समस्या यह है कि आप छोटी समस्याओं पर ध्यान केंद्रित करने पर कुछ छोटे (यानी रैपिंग नंबर) पर समयपूर्व अनुकूलन कर रहे हैं। मेरे द्वारा काम की जाने वाली कई चीजें एक कठिन वास्तविक समय सीमा है और समय के माइक्रो सेकेंड में निष्पादित होना चाहिए। –

+0

अच्छा अनुकूलन ट्रेवर –

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