2010-07-06 30 views
7

स्टैक ओवरव्लो भीड़। मेरे पास एक बहुत ही खुले अंत में सॉफ्टवेयर डिजाइन सवाल है।यूनिट रूपांतरण के लिए अच्छा डेटा संरचना?

मैं थोड़ी देर के लिए इसके लिए एक शानदार समाधान की तलाश में हूं और मैं सोच रहा था कि अगर किसी को यहां समस्या में कुछ शानदार अंतर्दृष्टि है। डेटा संरचना पहेली की तरह होने के लिए इस पर विचार करें।

जो मैं करने की कोशिश कर रहा हूं वह एक यूनिट कनवर्टर बनाना है जो कि किसी इकाई से किसी भी इकाई में परिवर्तित करने में सक्षम है। मान लीजिए कि लेक्सिंग और पार्सिंग पहले ही हो चुकी है। कुछ सरल उदाहरण:

Convert("days","hours")   // Yields 24 
Convert("revolutions", "degrees") // Yields 360 

बातें कुछ और जटिल बनाने के लिए, इसे सुचारू रूप से आदानों के बीच अस्पष्टता संभाल चाहिए:

Convert("minutes","hours")  // Yields (1/60) 
Convert("minutes","revolutions") // Yields (1/21600) 

चीजों को और भी अधिक मज़ा बनाने के लिए, यह करने के लिए की जरूरत के बिना जटिल इकाइयों को संभाल चाहिए सभी संभावनाओं का आकलन करें:

Convert("meters/second","kilometers/hour") 
Convert("miles/hour","knots") 
Convert("Newton meters","foot pounds") 
Convert("Acre feet","meters^3") 

कोई सही या गलत जवाब नहीं है, मैं इसे पूरा करने के तरीके पर विचारों की तलाश में हूं। हमेशा एक ब्रूट फोर्स समाधान होता है, लेकिन मुझे कुछ सुरुचिपूर्ण चाहिए जो सरल और स्केलेबल है।

+1

क्या आपको एकीकृत करने के लिए कुछ चाहिए? यदि आपको केवल डेटा की आवश्यकता है, तो 'इकाइयों (1) ' – Daenyth

+0

देखें, इसे किसी अन्य एप्लिकेशन में एकीकृत करने की आवश्यकता है, लेकिन मैंने कभी उस प्रोग्राम को नहीं देखा था। शायद मैं यह देख सकता हूं कि उन्होंने इसे पूरा करने के लिए क्या किया ... – riwalk

+0

कनवर्ट ("एकड़ पैर", "मीटर^3") के परिणाम क्या हैं? – Codism

उत्तर

0

मैं एक मेज

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

अस्पष्टताओं के लिए, प्रत्येक इकाई को मापने वाली सभी प्रकार की मात्रा से जोड़ा जा सकता है, और यह निर्धारित करने के लिए कि कौन सा रूपांतरण करना है, आप उन दो सेटों के अंतर को ले लेंगे (और यदि आपको 0 के साथ छोड़ दिया गया है या एक से अधिक आप एक त्रुटि थूकना होगा)

+0

एक अच्छी शुरुआत है, लेकिन सवाल की जटिलता को अनदेखा करता है। – riwalk

3

मैं एक हैशटेबल (या लगातार लुकअप टेबल - आपकी पसंद को कैसे कार्यान्वित करता हूं) से शुरू करूंगा जो आपके द्वारा रखे जाने वाले कई जोड़े के बीच यूनिट रूपांतरण करता है। अगर आप डालते हैं हर संभव जोड़ी में, तो यह आपके क्रूर बल दृष्टिकोण है।

यदि आपके पास केवल आंशिक जोड़े हैं, तो आप संयोजन को ढूंढने के लिए जोड़े गए जोड़ों में एक खोज कर सकते हैं। कोने पैर, इंच, और सेंटीमीटर, और किनारे कर रहे हैं:

Feet|Inches|1/12 
Inches|Centimeters|2.54 
अब

अगर मैं सेंटीमीटर फीट परिवर्तित करना चाहते हैं, मैं एक साधारण ग्राफ खोज है: उदाहरण के लिए, मान लीजिए मैं अपने hashtable में इन दो प्रविष्टियाँ जाने 1/12 और 2.54 रूपांतरण कारक। इस मामले में समाधान दो किनारों 1/12, 2.54 (निश्चित रूप से गुणा के माध्यम से संयुक्त) है। यदि आप चाहते हैं तो आप ग्राफ़ पैरामीटर के साथ फैनसीयर प्राप्त कर सकते हैं।

एक अन्य दृष्टिकोण अपहरणशील तर्क लागू कर रहा है - इस के लिए बीजगणितीय समस्या हलकों के बारे में एआई ग्रंथों को देखें ...

संपादित करें: को संबोधित करते यौगिक इकाइयों

सरलीकृत समस्या: कन्वर्ट "एकड़" से "मीटर^2"

इस मामले में, कुंजी को समझने रहे हैं कि हम लंबाई की इकाइयों के बारे में बात कर रहे हैं, इसलिए हम इकाई प्रकार के लिए तालिका में एक नया स्तंभ क्यों नहीं डालते हैं, जो "लंबाई" या "क्षेत्र" हो सकता है। यह पहले के मामलों में भी प्रदर्शन में मदद करेगा क्योंकि यह आपको अपनी खोज स्थान को कम करने के लिए एक आसान कॉलम देता है।

अब यह चाल है कि लंबाई^2 = क्षेत्र को समझना है। क्यों नहीं एक और देखने कि इस मेटाडाटा स्टोर खोलने:

Area|Length|Length|* 

हम जोड़े को प्राथमिक इकाइयों तालिका के साथ इस:

Meters|Feet|3.28|Length 
Acres|Feet^2|43560|Area 

तो एल्गोरिथ्म जाता है:

  • समाधान मीटर^2 है, जो एम * मीटर है, जो लंबाई * लंबाई है।
  • इनपुट एकड़ है, जो एक क्षेत्र है।
  • मीटर के लिए मेटा तालिका खोजें, और लंबाई * लंबाई मैपिंग खोजें। ध्यान दें कि अधिक जटिल उदाहरणों में एक से अधिक मान्य मानचित्रण हो सकते हैं।
  • समाधान में शामिल एक रूपांतरण Acres-> Feet^2।
  • फीट-> एम के लिए मूल ग्राफ खोज करें।

ध्यान दें कि:

  • एल्गोरिथ्म बुनियादी डोमेन जिसमें काम करने के लिए के रूप में क्षेत्र या लंबाई का उपयोग करने के लिए कि क्या पता नहीं चलेगा। आप इसे संकेत प्रदान कर सकते हैं, या इसे दोनों रिक्त स्थान खोज सकते हैं।
  • मेटा टेबल थोड़ा क्रूर-बल-आश ​​हो जाता है।
  • यदि आप मिश्रण प्रकार (उदा। प्रतिरोध = वोल्टेज/वर्तमान) शुरू करते हैं या वास्तव में कुछ बदसूरत और मिश्रित इकाई प्रणालियों (जैसे एक FooArea = मीटर * फीट) करना शुरू करते हैं तो मेटा तालिका को बेहतर होने की आवश्यकता होगी।
+0

मैंने यह दृष्टिकोण किया है, और यह अच्छी तरह से काम करता है, लेकिन आपको पहले से परिवर्तित राशि के साथ एक रूपांतरण पथ को पार करने की देखभाल करने की आवश्यकता नहीं है, क्योंकि त्रुटियां बहुत तेज़ी से जमा होती हैं। – codekaizen

+0

सहमत हैं, आपको लूप से बचने के लिए और चीजों को और भी जटिल हो सकता है यदि आप समांतर किनारों की अनुमति देते हैं (सुनिश्चित नहीं है कि यह सीधे इकाई रूपांतरण पर कैसे लागू होता है, लेकिन शायद सटीकता के विभिन्न स्तरों के साथ बाह्य कार्यों के लिए कॉलआउट) हैं। – Greg

+0

यह उत्तर बंद हो रहा है, लेकिन अभी भी एकड़ फीट -> मीटर^3 समाधान के साथ परेशानी होगी। कोई धारणा नहीं है कि इकाइयां एक ही "शैली" में होंगी। – riwalk

0

मुझे लगता है कि आप किसी प्रकार के ट्रिपल (fstUnit, sndUnit, multiplier) में रूपांतरण के बारे में डेटा रखना चाहते हैं।

एकल इकाई रूपांतरण के लिए: एक नंबर करने के इकाई संरचना बदलने के लिए, और फिर एक मैट्रिक्स में सभी मल्टीप्लायरों डाल करने के लिए O(1) में कुछ हैश फंक्शन का उपयोग करें (आप केवल ऊपरी-दाएँ भाग याद करने के लिए है, क्योंकि प्रतिबिंब है वही, लेकिन उलटा)।

जटिल मामलों के लिए: उदाहरण 1. एम/एस से किमी/घंटा। आप मैट्रिक्स में (एम, किमी) की जांच करें, फिर (एस, एच), फिर परिणामों को गुणा करें। उदाहरण 2. एम^3 से किमी^3। आप (एम, किमी) की जांच करें और इसे तीसरी शक्ति पर ले जाएं।

बेशक कुछ त्रुटियां, जब प्रकार फ़ील्ड और वॉल्यूम की तरह मेल नहीं खाते हैं।

0

आप यूनिट्स के लिए एक कक्षा बना सकते हैं जो रूपांतरण कारक और सभी मूल इकाइयों के घाटे को लेता है (मैं इसके लिए मीट्रिक इकाइयों का उपयोग करने का सुझाव देता हूं, जो आपके जीवन को आसान बनाता है)। जैसेछद्म जावा में:


public class Unit { 
    public Unit(double factor, int meterExp, int secondExp, int kilogrammExp ... [other base units]) { 
    ... 
    } 
} 

//you need the speed in km/h (1 m/s is 3.6 km/h): 
Unit kmPerH = new Unit(1/3.6, 1, -1, 0, ...) 

2

जो संरचना आप चुनते हैं, और अपनी पसंद अच्छी तरह से अपनी पसंद के कार्यान्वयन द्वारा निर्देशित किया जा सकता है (?? OO कार्यात्मक डीबीएमएस तालिका) मुझे लगता है कि आप खुद को इकाइयों की संरचना को पहचानने की जरूरत है।

उदाहरण के लिए 1000 किमी/घंटा की माप कई घटक हैं:

  • एक अदिश परिमाण, 1000;
  • एक उपसर्ग, इस मामले में किलो; और
  • एक आयाम, इस मामले में एलटी^(- 1), यानी, लंबाई के अनुसार लंबाई विभाजित है।

इकाइयों के साथ माप के आपके मॉडलिंग को कम से कम इस जटिलता को पकड़ने की आवश्यकता है।

जैसा कि पहले से ही सुझाव दिया गया है, आपको यह निर्धारित करना चाहिए कि आप किस इकाई का उपयोग करने जा रहे हैं, और एसआई बेस इकाइयां तुरंत खुद को सुझाती हैं। मॉडलिंग इकाइयों के लिए आपकी डेटा संरचना को तब उन बेस इकाइयों के संदर्भ में परिभाषित किया जाएगा। इसलिए आपको एक तालिका परिभाषित कर सकता है (RDBMS सोच यहाँ है, लेकिन आसानी से अपना पसंदीदा कार्यान्वयन में अनुवाद) जैसे प्रविष्टियों के साथ:

unit name  dimension     conversion to base 

foot   Length     0.3048 
gallon(UK)  Length^3     4.546092 x 10^(-3) 
kilowatt-hour Mass.Length^2.Time^(-2) 3.6 x 10^6 

और इसके आगे। आपको उपसर्गों (किलो-, नैनो-, मेगा-, मिबी- आदि) को गुणा करने के लिए एक तालिका की आवश्यकता होगी, और प्रत्येक आयाम के लिए आधार इकाइयों की एक तालिका (यानी लंबाई लंबाई के लिए आधार इकाई है, दूसरा समय के लिए, आदि)। आपको feet जैसी इकाइयों से निपटना होगा जो कि अन्य इकाइयों के लिए समानार्थी शब्द हैं।

आयाम का उद्देश्य निश्चित रूप से यह सुनिश्चित करने के लिए है कि आपके रूपांतरण और अन्य संचालन (जैसे 2 feet3.5 metres जोड़ना) अनुरूप हैं।

और, आगे पढ़ने के लिए, मैं this book by Cardarelli का सुझाव देता हूं।

संपादित टिप्पणियों के जवाब में ...

मैं सुझाव दे (कार्यान्वयन-विशिष्ट) समाधान से दूर नकल की तो मैं थोड़ा और वफ़ल जाएगा कोशिश कर रहा हूँ। कंपाउंड इकाइयां, जैसे किलोवाट-घंटे, एक समस्या उत्पन्न करते हैं। एक दृष्टिकोण कई यूनिट-एक्सप्रेशन, जैसे कि kilowatt और hour के साथ माप टैग करना होगा, और इस मामले में multiplication में उन्हें जोड़ने के लिए एक नियम होगा, मैं इसे बहुत तेज़ी से बालों वाली देख सकता था। आवेदन के डोमेन में इकाइयों के वैध सेट को सबसे आम लोगों तक सीमित करना बेहतर हो सकता है।

मिश्रित इकाइयों में माप से निपटने के लिए, एक इकाई के आयाम को परिभाषित करने का उद्देश्य यह सुनिश्चित करने के लिए कुछ साधन प्रदान करना है कि माप-इकाइयों के लिए केवल समझदार संचालन लागू किए जा सकें। तो, दो लंबाई (एल + एल) को एक साथ जोड़ना समझदार है, लेकिन लंबाई (एल) और वॉल्यूम (एल^3) नहीं। दूसरी ओर वॉल्यूम को लंबाई से विभाजित करना समझदारी है (एक क्षेत्र (एल^2) प्राप्त करने के लिए)। और यह निर्धारित करने के लिए आवेदन की तरह है कि प्रति वर्ग मीटर किलोवाट-घंटे जैसे अजीब इकाइयां वैध हैं या नहीं।

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

+0

मुझे "मेटा-इकाइयों" से यूनिट को अलग करना पसंद है। दूसरी तरफ, यह सभी संभावित विकल्पों की गणना करने के विचार की ओर जाता है। उदाहरण के लिए: किलोवाट-घंटे, किलोवाट-मिनट, किलोवाट-सेकेंड, किलोवाट-डे, किलोवाट-सप्ताह इत्यादि सभी काम करना चाहिए, भले ही वे जरूरी नहीं समझें। ऐसा कहा जा रहा है, यह भी एकड़ पैर की जटिलता से ग्रस्त है -> घन मीटर रूपांतरण। – riwalk

+0

अच्छा जवाब, वास्तव में संख्यात्मक मूल्यों, इकाई वर्गों (दूरी, समय, आदि) और विशेष इकाइयों (सेमी, एस, ...) को अलग करने की मूल आवश्यकता को प्राप्त करता है। –

+0

आपका सिस्टम, जैसा कि आप इसका वर्णन करते हैं, परमाणु इकाइयों के लिए वास्तव में सहज है।आप अंकगणितीय परिचालन करने का प्रयास कैसे करेंगे जहां यौगिक इकाइयों को शामिल किया गया है (वाट/एस, किलो/एम^3, आदि)? बहुत दयालु रहें और हमें कुछ यादृच्छिक विचार उच्च प्रदर्शन चिह्न दें। –

0

मैं इन क्षेत्रों के साथ एक मेज होगा:

conversionID 
fromUnit 
toUnit 
multiplier 

और आप

समर्थन करने के लिए आप एक बहु-चरण की प्रक्रिया का समर्थन करने के लिए (चाहते हैं चाहते हैं लेकिन कई पंक्तियों आप सभी रूपांतरणों की दुकान करने की आवश्यकता है सी करने के लिए एफ डिग्री), आप की तरह

conversionID 
sequence 
operator 
value 

इकाइयों की मेज, conversionStep कहा जाता है कहते हैं के साथ एक-से-अनेक संबंध, क्षेत्रों के साथ आवश्यकता होगी आप conversi का एक सेट संग्रहीत करना चाहते हैं ऑन लेकिन समर्थन बहु-चरण रूपांतरण,

Feet|Inches|1/12 
Inches|Centimeters|2.54 

भंडारण और पैर से सेंटीमीटर में कनवर्ट करने का समर्थन करने की तरह, मैं

conversionPlanID 
startUnits 
endUnits 
via 

अपने पंक्ति की तरह एक और तालिका में एक रूपांतरण योजना संग्रहीत करेंगे,

कैसा लगेगा
1 | feet | centimeters | inches 
+0

इसके साथ एकमात्र समस्या यह है कि एन इकाइयों के लिए, आपको तालिका में (एन 2 चुनें) फ़ील्ड होना होगा। न केवल स्मृति गहन है (जटिलता ओ (एन^2)), लेकिन यह एक काफी कठोर डेटा संरचना है। – riwalk

+0

यदि आप रिवर्स संयोजन को दोबारा स्टोर नहीं करना चाहते हैं, तो आप एक व्यस्त मल्टीप्लायर फ़ील्ड जोड़ सकते हैं, लेकिन एक उदाहरण जो मैं आपके उदाहरण में देख रहा हूं, इसलिए मुझे यकीन नहीं है कि आपको अन्य लचीलापन की आवश्यकता है। – Beth

+0

@ stargazer712 आप टेबल में पंक्तियों का मतलब है? तालिका में – Beth

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