Open In App

Design a Number System Conversion App using React-Native

Last Updated : 24 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In this article, we will build Number System Conversion App using React Native. The app e­nables users to seamle­ssly convert numbers among binary, decimal, octal, and he­xadecimal systems.

Prerequisites:

Steps to Create React Native Application

Step 1: Create a React Native Application

Create a new React Native project for NumberSystemConversionApp

npx create-expo-app NumberSystemConversionApp

Step 2: ​Change the directory to the project folder

cd NumberSystemConversionApp

Step 3: Install Required Packages

npm install number-to-words

Project Structure

package.json

{
"dependencies": {
"number-to-words": "*",
"@expo/vector-icons": "^13.0.0",
"react-native-paper": "4.9.2"
}
}

Approach:

  • UseState­ is a React hook that allows managing state in functional components. It's use­ful for initializing variables like inputFormat and inputNumber.
  • The function "handle­Conversion" is activated when the­ user clicks the "Convert" button. It proce­sses the user input and update­s the state with the conve­rted results.
  • The function floatToFraction is de­signed to help convert floating-point numbe­rs into fractions. It achieves this by identifying the­ fraction that
  • roundToKthInteger: Rounds numbers to a specified decimal place, using a power of 10.
  • The function "roundToSignificantDigits" pe­rforms the rounding of numbers to a specific se­t of significant digits. This is achieved by
  • The re­nderOptionItem function is utilized to display options in a modal dropdown by e­mploying the FlatList component. Updating the selected format on selection from the options.

Example: The Numbe­r Format Converter app, built using React Native­, allows users to effortlessly conve­rt numbers betwee­n various number systems such as binary, decimal, octal, and he­xadecimal. By inputting numbers into the app, use­rs can swiftly obtain equivalent values in diffe­rent formats using specialized conve­rsion functions. The app supports precision rounding and significant figures, and it e­ven offers the unique­ feature of converting numbe­rs into words. With its intuitive interface comprising a format se­lection dropdown and customization modal, users can easily switch be­tween differe­nt conversions. This functionality is enhanced by e­ncapsulated conversion functions that enable­ seamless switching.

CSS
//styles.js 
import { StyleSheet } from 'react-native'; 

const styles = StyleSheet.create({ 
	container: { 
		flex: 1, 
		padding: 20, 
		alignItems: 'center', 
		backgroundColor: '#f7f7f7', 
	}, 
	header: { 
		fontSize: 24, 
		marginBottom: 20, 
		textAlign: "center", 
		color: "green", 
		fontWeight: "bold", 
		margin: 20, 
	}, 
	dropdownButton: { 
		borderWidth: 1, 
		borderColor: '#ced4da', 
		borderRadius: 4, 
		padding: 8, 
		width: '100%', 
		marginBottom: 20, 
		alignItems: 'center', 
		backgroundColor: '#fff', 
	}, 
	section: { 
		backgroundColor: '#fff', 
		borderWidth: 1, 
		borderRadius: 7, 
		width: '100%', 
		maxWidth: 500, 
		padding: 20, 
		marginBottom: 20, 
	}, 
	inputContainer: { 
		flexDirection: 'row', 
		alignItems: 'center', 
	}, 
	input: { 
		flex: 1, 
		fontSize: 16, 
		padding: 8, 
		borderWidth: 1, 
		borderColor: '#ced4da', 
		borderRadius: 4, 
		marginRight: 5, 
		backgroundColor: '#fff', 
	}, 
	label: { 
		fontSize: 15, 
		color: '#000', 
		fontWeight: "bold", 
	}, 
	btn: { 
		fontSize: 16, 
		padding: 8, 
		borderRadius: 10, 
		backgroundColor: '#28a745', 
		marginLeft: 5, 
		shadowOffset: { width: 0, height: 6 }, 
		shadowColor: 'grey', 
		shadowOpacity: 0.5, 
		shadowRadius: 15, 
	}, 
	btnText: { 
		fontSize: 16, 
		padding: 8, 
		color: '#fff', 
		fontWeight: "bold", 
	}, 
	resultSection: { 
		marginBottom: 20, 
		backgroundColor: '#fff', 
		borderWidth: 1, 
		borderRadius: 7, 
		padding: 20, 
		width: '100%', 
		maxWidth: 500, 
		shadowOffset: { width: -2, height: 4 }, 
		shadowColor: 'grey', 
		shadowOpacity: 1, 
		shadowRadius: 13, 
	}, 
	resultHeader: { 
		fontSize: 18, 
		marginBottom: 10, 
	}, 
	resultText: { 
		fontSize: 19, 
		color: "red", 
		fontWeight: "bold", 
	}, 
	modalContainer: { 
		flex: 1, 
		justifyContent: 'center', 
		alignItems: 'center', 
		backgroundColor: 'rgba(0, 0, 0, 0.5)', 
	}, 
	modalContent: { 
		backgroundColor: 'white', 
		borderRadius: 10, 
		padding: 20, 
		width: '80%', 
		maxHeight: '80%', 
	}, 
	optionItem: { 
		padding: 10, 
		borderBottomWidth: 1, 
		borderBottomColor: '#ced4da', 
	}, 
	optionText: { 
		fontSize: 16, 
	}, 

}); 

export { styles }
JavaScript
// App.js 
import React, { useState } from 'react'; 
import { 
	View, 
	Text, 
	TextInput, 
	Button, 
	StyleSheet, 
	Modal, 
	TouchableOpacity, 
	FlatList, 
	ScrollView, 
} from 'react-native'; 
import numberToWords from 'number-to-words'; 
import { styles } from "./styles"; 


export default function Numberformat() { 
	let [inputFormat, setInputFormat] = useState('decimal'); 
	let [inputNumber, setInputNumber] = useState(''); 
	let [decimal, setDecimal] = useState(''); 
	let [binary, setBinary] = useState(''); 
	let [octal, setOctal] = useState(''); 
	let [hexadecimal, setHexadecimal] = useState(''); 
	let [rounddigit, setRoundDigit] = useState(''); 
	let [rounddigitindex, setRoundDigitindex] = useState('2'); 
	let [significantno, setSignificantno] = useState(''); 
	let [significantnoindex, setSignificantnoindex] = useState('2'); 
	let [integer, setInteger] = useState(''); 
	let [numerator, setNumerator] = useState('0'); 
	let [denominator, setDenominator] = useState('0'); 
	let [inword, setInword] = useState(''); 
	let [modalVisible, setModalVisible] = useState(false); 
	let [options] = useState([ 
		{ label: 'Binary', value: 'binary' }, 
		{ label: 'Decimal', value: 'decimal' }, 
		{ label: 'Octal', value: 'octal' }, 
		{ label: 'Hexadecimal', value: 'hexadecimal' }, 
	]); 

	// Conversion functions object 
	const conversionFunctions = { 
		binary: (input) => parseInt(input, 2), 
		octal: (input) => parseInt(input, 8), 
		hexadecimal: (input) => parseInt(input, 16), 
		decimal: (input) => parseInt(input, 10), 
	}; 

	const handleConversion = () => { 
		const decimalValue = 
			conversionFunctions[inputFormat](inputNumber); 

		setDecimal(decimalValue); 
		setInteger(Math.floor(decimalValue).toString()); 
		setBinary(Math.floor(decimalValue).toString(2)); 
		setOctal(Math.floor(decimalValue).toString(8)); 
		setHexadecimal(Math.floor(decimalValue) 
			.toString(16).toUpperCase()); 

		if (decimalValue <= 1000000000000000) { 
			setInword(numberToWords.toWords(decimalValue)); 
		} else { 
			setInword("Over Limit (Max-Limit: 1000000000000000)"); 
		} 

		setRoundDigit(roundToKthInteger( 
			parseFloat(decimalValue, 10), 
			parseInt(rounddigitindex, 10)) 
		); 

		if (inputFormat === 'decimal' && 
			parseFloat(decimal, 10) - decimalValue !== 0) { 
			const result = floatToFraction( 
				parseFloat(decimal, 10) - decimalValue); 
			setNumerator(result.numerator.toString()); 
			setDenominator(result.denominator.toString()); 
		} else { 
			setNumerator('0'); 
			setDenominator('0'); 
		} 

		if (inputFormat === 'decimal') { 
			setSignificantno(roundToSignificantDigits( 
				parseFloat(decimal, 10), 
				parseInt(significantnoindex, 10) 
			)); 
		} else { 
			setSignificantno(roundToSignificantDigits( 
				parseFloat(decimalValue, 10), 
				parseInt(significantnoindex, 10) 
			)); 
		} 
	}; 

	function floatToFraction(number) { 
		const tolerance = 0.000001; 
		let numeratorvalue = 1; 
		let denominatorvalue = 1; 
		let error = number - numeratorvalue / denominatorvalue; 

		while (Math.abs(error) > tolerance) { 
			if (error > 0) numeratorvalue++; 
			else denominatorvalue++; 
			error = number - numeratorvalue / denominatorvalue; 
		} 
		return { 
			numerator: numeratorvalue, 
			denominator: denominatorvalue 
		}; 
	} 

	function roundToKthInteger(number, k) { 
		const multiplier = Math.pow(10, k); 
		return Math.round(number * multiplier) / multiplier; 
	} 

	function roundToSignificantDigits(number, significantDigits) { 
		if (significantDigits <= 0) return 0; 
		const multiplier = Math.pow(10, 
			significantDigits - Math.floor 
			(Math.log10(Math.abs(number))) - 1); 
		const roundedNumber = 
			(Math.round(number * multiplier) / multiplier); 
		return roundedNumber; 
	} 

	const renderOptionItem = ({ item }) => ( 
		<TouchableOpacity 
			style={styles.optionItem} 
			onPress={() => { 
				setInputFormat(item.value); 
				setModalVisible(false); 
			}} 
		> 
			<Text style={styles.optionText}>{item.label}</Text> 
		</TouchableOpacity> 
	); 

	return ( 
		<ScrollView> 
			<View style={styles.container}> 
				<Text style={styles.header}> 
					Number Format Converter 
				</Text> 
				<TouchableOpacity 
					style={styles.dropdownButton} 
					onPress={() => setModalVisible(true)} 
				> 
					<Text>{inputFormat}</Text> 
				</TouchableOpacity> 
				<View style={styles.section}> 
					<Text style={styles.label}> 
						Enter {inputFormat} Number 
					</Text> 
					<View style={styles.inputContainer}> 
						<TextInput 
							style={styles.input} 
							keyboardType={ 
								(inputFormat !== 'decimal') ? "default" : "numeric"
							} 
							value={inputNumber} 
							onChangeText={(text) => { 
								if (inputFormat === 'decimal') { 
									setDecimal(text); 
									setInputNumber(text); 
								} else { 
									setInputNumber(text); 
								} 
							}} 
						/> 
						<TouchableOpacity 
							style={styles.btn} 
							onPress={handleConversion} 
						> 
							<Text style={styles.btnText}>Convert</Text> 
						</TouchableOpacity> 
					</View> 
				</View> 
				{/* Display the conversion results here */} 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}> 
						Integer Number 
					</Text> 
					<Text style={styles.resultText}>{integer}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}> 
						Binary Format (Base-2) of Integer {integer} 
					</Text> 
					<Text style={styles.resultText}>{binary}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}> 
						Octal Format (Base-8) of Integer {integer} 
					</Text> 
					<Text style={styles.resultText}>{octal}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}> 
						Hexadecimal Format (Base-16) of Integer {integer} 
					</Text> 
					<Text style={styles.resultText}>{hexadecimal}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}> 
						In Words of Integer {integer} 
					</Text> 
					<Text style={styles.resultText}>{inword}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}>Rounded Number</Text> 
					<Text style={styles.resultText}>{rounddigit}</Text> 
				</View> 
				<View style={styles.resultSection}> 
					<Text style={styles.resultHeader}>Significant Number</Text> 
					<Text style={styles.resultText}>{significantno}</Text> 
				</View> 

				{/* Modal for Options */} 
				<Modal 
					animationType="slide"
					transparent={true} 
					visible={modalVisible} 
					onRequestClose={() => setModalVisible(false)} 
				> 
					<View style={styles.modalContainer}> 
						<View style={styles.modalContent}> 
							<FlatList 
								data={options} 
								renderItem={renderOptionItem} 
								keyExtractor={(item) => item.value} 
							/> 
						</View> 
					</View> 
				</Modal> 
			</View> 
		</ScrollView> 
	); 
}

Steps to Run:

To run react native application use the following command:

npx expo start
  • To run on Android:
npx react-native run-android
  • To run on iOS:
npx react-native run-ios

Output:


Next Article

Similar Reads