'javascript'에 해당되는 글 15건

  1. 2024.01.16 Decimal calculation in Javascript 1
  2. 2022.03.01 let, var, const 차이점
  3. 2021.03.25 React 클래스로 선언, 자식컴포넌트
  4. 2021.03.25 React 기초 연습
  5. 2021.03.21 var let const
  6. 2021.03.20 타일 깔기
  7. 2021.03.20 javascript 2차원배열의 얕은 복사
  8. 2021.03.19 Git 사용하기

Decimal calculation in Javascript

웹 개발/Problems 2024. 1. 16. 02:10

자바스크립트를 이용해 실수의 연산을 하다보면 소수점이 이상하게 나타나는 경우가 있다. 컴퓨터는 기본적으로 이진수를 이용하기 때문에 실수를 다루는 방식은 컴퓨팅 언어마다 다르다. Javascript는 모든 숫자를 IEEE 754 표준을 따르는 배정밀도 64 비트 부동 소수점 형식으로 표현하며, 이 형식은 실수를 근사치로 저장한다.

따라서 0.6 / 0.2 와 같은 연산을 실행 해보면 3이 아닌 2.999999999996 와 같은 예측에서 벗어난 값이 나온다. 이를 해결하기 위해 실수를 정수로 바꾼 후에 연산을 하고 다시 원래 실수로 돌려놓는 방법을 사용한다.

function findMostDecimal(array: number[]): number {
    let maxDecimal = 0;
    let numberWithMostDecimals = array[0];

    for (let num of array) {
        let decimalCount = countDecimalPlaces(num);
        if (decimalCount > maxDecimal) {
            maxDecimal = decimalCount;
            numberWithMostDecimals = num;
        }
    }

    return numberWithMostDecimals;
}

먼저 실수들 중에서 가장 소수점 자리가 큰 실수를 알아낸다.

export function countDecimalPlaces_10(value: number): number {
    if (!isFinite(value)) return 0; //무한대나 NaN인 경우, 0을 반환
    let text = value.toString();
    let index = text.indexOf('.');
    if (index === -1) return 1; //소수점이 없는 경우, 1을 반환. (정수이므로)
    let decimalPart = text.substring(index + 1);
    return Math.pow(10, decimalPart.length);
}

실수를 정수로 바꾸기 위해 지수를 구한다.

 

export function operateDecimals(
    value1: number,
    value2: number,
    operation: Tadjuster_method,
) {
    const mostDecimal = findMostDecimal([value1, value2]);
    const factor = countDecimalPlaces_10(mostDecimal);
    const newValue1 = Math.floor(value1 * factor);
    const newValue2 = Math.floor(value2 * factor);
    let result;
    switch (operation) {
        case 'add':
            result = (newValue1 + newValue2) / factor;
            break;
        case 'subtract':
            result = (newValue1 - newValue2) / factor;
            break;
        case 'multiply':
            result = (newValue1 * newValue2) / (factor * factor);
            break;
        case 'divide':
            result = newValue1 / newValue2; // 나눗셈의 경우, factor로 나눌 필요 없음
            break;
        default:
            throw new Error('Invalid operation');
    }
    return result;
}

이렇게 정수로 바꾼다음 연산을 진행한 뒤 지수를 다시 나눠주면 원하는 값을 구할 수 있다.

:

let, var, const 차이점

웹 개발/Study 2022. 3. 1. 02:00

1. 변수 선언 방식

var는 한번 선언한 변수일지라도 중복해서 선언을 할 수 있는 특징이 있다.

var a = 1;
console.log(a)//1
var a = 2;
console.log(a)//2

위와 같이 한번 선언을 한 a 변수 일지라도 var태그를 사용하여 선언 하면 다시 선언을 할 수 있다. 이는 간단한 테스트에는 편리할 수 있으나 코드량이 많아진다면 어디에서 사용했었는지 파악하기가 어렵고 기존의 값이 바뀌어 버그가 발생할 수 있다.

이와 달리 let과 const는 재선언이 불가능하다. 하지만 이 둘에도 차이점이 있는데, 그것은 immutable여부이다.

let은 변수에 재할당이 가능하고, const는 불가능하다.

2. 호이스팅

호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다.

자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const function function*, class)을 호이스팅한다.

하지만, var 로 선언된 변수와 달리 let로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.

console.log(foo);//undefined
var foo;

console.log(bar); //Error: Uncaught ReferenceError: bar is not defined
let bar;

이는 let 로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

참고로 변수는 선언 단계 > 초기화 단계 > 할당 단계에 걸쳐 생성되는데,

var 으로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 하지만 let으로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.

//스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
//따라서 변수 선언문 이전에 변수를 참조할 수 있다.

console.log(foo);

var foo;
console.log(foo);
foo = 1; //할당문에서 할당 단계가 실행된다.
console.log(foo); //1
//스코프의 선두에서 선언단계가 실행된다.
//아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
//따라서 변수 선언문 이전에 변수를 참조할 수 없다.

console.log(foo); //ReferenceError: foo is not defined

let foo; //변수 선언문에서 초기화 단계가 실행된다
console.log(foo); //undefined

foo = 1; //할당문에서 할당 단계가 실행된다.
console.log(foo); //1

3. 정리

변수 선언에는 기본적으로 const를 사용하고, 재할당이 필요한 경우에 한정해 let을 사용하는것이 좋다.

그리고 객체를 재할당하는 경우는 생각보다 흔하지 않다. const를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.

 

'웹 개발 > Study' 카테고리의 다른 글

babel 과 polyfill  (0) 2022.03.02
Closure, 클로저 함수  (0) 2022.03.01
웹팩 dependencies 설정  (0) 2021.08.20
React 기초 연습  (0) 2021.03.25
객체 지향 설계의 다섯가지 원칙  (0) 2021.03.21
:

React 클래스로 선언, 자식컴포넌트

카테고리 없음 2021. 3. 25. 17:06

App.js:

import './App.css'
import React from 'react';
const username = "annonymous"

class Twittler extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            tweets: []
        }
        this.handleButtonClick = this.handleButtonClick.bind(this)
    }
    handleButtonClick(){
        let tweetArr = this.state.tweets.slice()
        tweetArr.push({username: username, text: document.getElementById("textBox").value, time: new Date().toLocaleTimeString()})
        this.setState({tweets: tweetArr})
    }
    render(){        
        return (
            <header className="App-header">
				<div className="textBox-Button">
                    <textarea id="textBox"></textarea>
					<NewTweetForm handleButtonClick = {this.handleButtonClick} />
				</div>
                <div id = "tweets">
                    <Tweets arr = {this.state.tweets}/>
                </div>
                <div>this is app2</div>
			</header>            
        )
    }
}

function NewTweetForm({handleButtonClick}){
    let handleClick = ()=>{
        handleButtonClick()
    }
    return <button id= "postButton" onClick= {handleClick.bind(this)} >Post</button>
}
function makeArr(arr){
    return arr.map((el,idx)=>{
        return <li key = {idx.toString()}>
            <div>{el.username}</div>
            <div>{el.text}</div>
            <div>{el.time}</div>
            <hr/>
        </li>
    })
}

function Tweets ({arr}){   
    return (
        <ul id = "ul">{                
            makeArr(arr)
        }</ul>
    )
}


function App(){
    return (
		<div className="App">
			<Twittler />
		</div>
	);
}
export default App

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
    <App />,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
:

React 기초 연습

웹 개발/Study 2021. 3. 25. 17:02

App.js:

import './App.css';
import ReactDOM from 'react-dom';
let tweet = <div>{Tweet({ writer: '이호준' })}</div>;
let tweet2 = (
	<div>
		{(function () {
			return '리액트';
		})()}
	</div>
);
let nowLearning = false;

let tweet3 = (
	<Tweet writer="김코딩">
		{(function () {
			if (nowLearning) {
				return '리액트';
			} else {
				return '배틀그라운드';
			}
		})() + '는 늘 짜릿하네요'}
	</Tweet>
);
function Tweet4(){
	let langs = ["javascript", 'HTML', 'Python']
	// eslint-disable-next-line
	return (
		<div>
			{langs.map(it=><div>{it}</div>)}
		</div>
	)
}
function Tweet({ writer, children }) {
	return (
		<div>
			{writer}
			{children}
		</div>
	);
}
function clock() {
	ReactDOM.render(
		<div>{new Date().toLocaleTimeString()}</div>,
		document.getElementById('clock'),
	);
}
setInterval(clock, 1000);
function App() {
	return (
		<div className="App">
			<header className="App-header" id="App-header">
				<h1>Hello World!</h1>
				<h2>Start editing to see some magic happen!</h2>
				{tweet}
				{tweet2}
				{tweet3}
				<Tweet4 />
				<div id="clock">{new Date().toLocaleTimeString()}</div>
			</header>
		</div>
	);
}

export default App;

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App.js';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(<App />, document.getElementById('root'));

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

'웹 개발 > Study' 카테고리의 다른 글

let, var, const 차이점  (0) 2022.03.01
웹팩 dependencies 설정  (0) 2021.08.20
객체 지향 설계의 다섯가지 원칙  (0) 2021.03.21
var let const  (0) 2021.03.21
Git 사용하기  (0) 2021.03.19
:

var let const

웹 개발/Study 2021. 3. 21. 17:03

var, let, const의 차이점

1. var는 함수 레벨 스코프이고 let, const는 블럭 레벨 스코프입니다.

2. var로 선언한 변수는 선언 전에 사용해도 에러가 나지 않지만 let, const는 에러가 발생합니다.

3. var는 이미 선언되어있는 이름과 같은 이름으로 변수를 또 선언해도 에러가 나지 않지만 let, const는 이미 존재하는 변수와 같은 이름의 변수를 또 선언하면 에러가 납니다.

4. var, let은 변수 선언시 초기 값을 주지 않아도 되지만 const는 반드시 초기값을 할당해야 합니다.

5. var, let은 값을 다시 할당할 수 있지만 const는 한번 할당한 값은 변경할 수 없습니다(단, 객체 안에 프로퍼티가 변경되는 것까지 막지는 못합니다).

함수레벨 스코프란?

// var는 function-scope이기 때문에 for문이 끝난다음에 i를 호출하면 값이 출력이 잘 된다.
// 이건 var가 hoisting이 되었기 때문이다.
for(var j=0; j<10; j++) {
  console.log('j', j)
}
console.log('after loop j is ', j) // after loop j is 10


// 아래의 경우에는 에러가 발생한다.
function counter () {
  for(var i=0; i<10; i++) {
    console.log('i', i)
  }
}
counter()
console.log('after loop i is', i) // ReferenceError: i is not defined

 

'웹 개발 > Study' 카테고리의 다른 글

React 기초 연습  (0) 2021.03.25
객체 지향 설계의 다섯가지 원칙  (0) 2021.03.21
Git 사용하기  (0) 2021.03.19
Node 명령어  (0) 2021.03.19
HTTP 상태 코드/ 요청 메서드  (0) 2021.03.19
:

타일 깔기

웹 개발/Algorithm 2021. 3. 20. 16:38
더보기

문제

세로 길이 2, 가로 길이 n인 2 x n 보드가 있습니다. 2 x 1 크기의 타일을 가지고 이 보드를 채우는 모든 경우의 수를 리턴해야 합니다.

입력

인자 1 : n

  • number 타입의 1 이상의 자연수

출력

  • number 타입을 리턴해야 합니다.

주의사항

  • 타일을 가로, 세로 어느 방향으로 놓아도 상관없습니다. (입출력 예시 참고)

입출력 예시

let output = tiling(2);
console.log(output); // --> 2

output = tiling(4);
console.log(output); // --> 5
/* 
2 x 4 보드에 타일을 놓는 방법은 5가지
각 타일을 a, b, c, d로 구분

2 | a b c d
1 | a b c d 
------------

2 | a a c c
1 | b b d d 
------------

2 | a b c c
1 | a b d d 
------------

2 | a a c d
1 | b b c d 
------------

2 | a b b d
1 | a c c d 
------------
*/

Advanced

  • 타일링 문제를 해결하는 효율적인 알고리즘(O(N))이 존재합니다. 반드시 직접 문제를 해결하시면서 입력의 크기에 따라 어떻게 달라지는지 혹은 어떻게 반복되는지 관찰하시기 바랍니다.

 

답안1(시간복잡도 계산 x, 무식하게 하나씩 둬보기!):

더보기
let tiling = function (n) {
	// TODO: 여기에 코드를 작성합니다.
	let count = 0;
	let ground = [];
	for (let i = 0; i < 2; i++) {
		//세로길이 2
		ground.push(new Array(n).fill(0));
	}
	//[0, 0, 0, 0, 0]
	//[0, 0, 0, 0, 0]
	//{1: [[0,0],[1,0]]} 1번 타일
	//{2: [[0,1],[1,1]]} or {2: [[0,1],[0,2]]} 2번 타일
	let find0 = function (changedField) {
		for (let i = 0; i < changedField.length; i++) {
			for (let j = 0; j < changedField[i].length; j++) {
				if (changedField[i][j] === 0) {
					return [i, j];
				}
			}
			//다 채워지면
		}
		return null;
	};
	//startIndex = find0(field)
	let putTile = function (field) {
		//가로로 넣어보기 --> x축에 +1
		if (find0(field) === null) {//필드가 다 채워지면			
			count++;
		} else {
			let [y, x] = find0(field);
			//세로로 넣어보기
			if (field[y + 1] !== undefined) {
				if (field[y + 1][x] === 0) {
					//세로로 놓아지는지 확인
					//let copyfield = field.slice();
					let copyfield = [];
					for (let row of field) {//2차원 배열을 복사할땐 이렇게 해야한다!!
						copyfield.push(row.slice());
					}
					copyfield[y][x] = 1;
					copyfield[y + 1][x] = 1;					
					putTile(copyfield);				
				}
			}
			if (field[y][x + 1] === 0) {
				//가로로 놓아지는지 확인
				let copyfield = [];
				for (let row of field) {
					copyfield.push(row.slice());
				}
				copyfield[y][x] = 1;
				copyfield[y][x + 1] = 1;
				putTile(copyfield); // 다음 타일 놓기
			}

			//넣고 재귀 돌리기
			//다 채워지면 count++
		}
	};
	putTile(ground);
	return count;
};

 

답안2(시간복잡도 계산. O(n)):

더보기
// naive solution: O(2^N)
// 2 x 4 보드에 타일을 놓는 방법은 5가지다.
// 각 타일을 a, b, c, d로 구분한다.
// 아직 타일이 놓이지 않는 부분은 -로 표기한다.
// 타일을 놓는 방법은 가장 왼쪽부터 세로로 놓거나 가로로 놓는 것으로 시작한다.
// 1) 세로로 놓는 법
//   2 | a - - -
//   1 | a - - -
//   ------------
// 2) 가로로 놓는 법
// 타일을 가로로 놓게 되면, 그 바로 아래에는 가로로 놓을 수 밖에 없다.
//   2 | a a - -
//   1 | b b - -
//   ------------
// 이때, 타일이 아직 놓이지 않은 부분은 사실 크기만 다를뿐 같은 종류의 문제라는 것을 알 수 있다.
// 즉, 2 x 4 보드에 타일을 놓는 방법은 아래 두 가지 방법을 더한 결과와 같다.
//  1) 2 x 3 보드에 타일을 놓는 방법
//  2) 2 x 2 보드에 타일을 놓는 방법
// 따라서 2 x n 타일 문제는 아래와 같이 재귀적으로 정의할 수 있다.
// 주의: 재귀적 정의에는 항상 기초(base), 즉 더 이상 재귀적으로 정의할 수 없는(쪼갤 수 없는) 문제를 별도로 정의해야 한다.
// let tiling = function (n) {
//   if (n <= 2) return n;
//   return tiling(n - 1) + tiling(n - 2);
// };

// dynamic with memoization: O(N)
let tiling = function (n) {
  // 인덱스를 직관적으로 관리하기 위해
  // 앞 부분을 의미없는 데이터(dummy)로 채운다.
  const memo = [0, 1, 2];

  // 재귀를 위한 보조 함수(auxiliary function)을 선언)
  const aux = (size) => {
    // 이미 해결한 문제는 풀지 않는다.
    if (memo[size] !== undefined) return memo[size];
    if (size <= 2) return memo[n];
    memo[size] = aux(size - 1) + aux(size - 2);
    return memo[size];
  };
  return aux(n);
};

// dynamic with tabulation: O(N)
// tabulation은 데이터를 테이블에 정리하면서 bottom-up 방식으로 해결하는 기법을 말합니다.
// let tiling = function (n) {
//   const memo = [0, 1, 2];
//   if (n <= 2) return memo[n];
//   for (let size = 3; size <= n; size++) {
//     memo[size] = memo[size - 1] + memo[size - 2];
//   }
//   return memo[n];
// };

// dynamic with slicing window: O(N)
// slicing window은 필요한 최소한의 데이터만을 활용하는 것을 말합니다.
// 크기 n의 문제에 대한 해결을 위해 필요한 데이터는 오직 2개뿐이라는 사실을 이용합니다.
// let tiling = function (n) {
//   let fst = 1,
//     snd = 2;
//   if (n <= 2) return n;
//   for (let size = 3; size <= n; size++) {
//     // 앞의 두 수를 더해 다음 수를 구할 수 있다.
//     const next = fst + snd;
//     // 다음 문제로 넘어가기 위해 필요한 2개의 데이터의 순서를 정리한다.
//     fst = snd;
//     snd = next;
//   }
//   return snd;
// };

'웹 개발 > Algorithm' 카테고리의 다른 글

효율적인 피보나치  (0) 2021.03.15
집밥이 그리워  (0) 2021.03.11
빼빼로 데이(최대공약수)  (0) 2021.03.11
발표 순서  (0) 2021.03.11
금고를 털어라  (0) 2021.03.11
:

javascript 2차원배열의 얕은 복사

Ubuntu/삽질하기 2021. 3. 20. 16:13
let arr = [[1,2],[3,4]]
let arr2 = arr.slice()
arr2[0][0] = 5
//arr의 값은?

 

위의 문제에서 arr의 값은 아주 소름돋게도 [[5,2],[3,4]]가 된다.

arr.slice()함수가 원본배열을 그대로 복사해서 arr2에 넣어줘서 arr2의 값을 아무렇게나 바꿔줘도 원본 배열인 arr의 값은 안바뀔줄 알고 한참을 헤맸다... 그러다가 혹시나 하는 마음에 찍어 보니 원본배열을 바꾸고있었다!!! 

slice()함수가 배열안의 값을 하나씩 끄집어 내서 넣어주는 방식으로 복사가 이루어 지다보니 결국 arr2자체는 arr의 주소값을 참조하지 않지만 arr2의 요소 하나하나는 arr의 요소들의 주소값을 참조를 하고 있었던것이다.

따라서 for문을 이용해 복사를 해줘야한다... ㄷㄷ 소름

'Ubuntu > 삽질하기' 카테고리의 다른 글

그래픽 드라이버 nouveau 에서 nvidia로 변경하기  (0) 2021.02.23
:

Git 사용하기

웹 개발/Study 2021. 3. 19. 18:45

git remote add pair <Repo URL for pairs fork>

git remote -v

페어의 레버지토리 연결

 

git add<change file>

git commit -m “memo”

git push origin master ( or other branch name)

push는 자신의 레포지토리에다가 해야함

 

git pull pair master ( or other branch name)

pull은 항상 페어의 레포지토리에서 해야함

페어의 레포지토리에서 변경사항 가져오기

 

git add <change file>

git commit -m “change”

 

git pull pair master

 

 

git config credential.helper store

인증을 캐시에 저장하여 일정시간동안 입력하지 않는다.

 

git config –global credential.hgelper ‘cache –timeout 7200’

timeout뒤의 숫자는 초(second)이다. 여기서는 7200만큼(2시간)의 만료시간을 추가했다.

1day – 86400

7days – 604800

30days – 2592000

 

git checkout

branch 이동

 

git checkout -b 기능1

현재 작업공간을 베이스로 브랜치 생성

기능1 branch 생성 + 기능1 branch로 작업공간 이동

 

git branch

branch확인, q로 나가기

 

'웹 개발 > Study' 카테고리의 다른 글

객체 지향 설계의 다섯가지 원칙  (0) 2021.03.21
var let const  (0) 2021.03.21
Node 명령어  (0) 2021.03.19
HTTP 상태 코드/ 요청 메서드  (0) 2021.03.19
Promise 정리  (0) 2021.03.19
: