I have an issue with the result of additions and subtractions if the result is less than 5. Top many decimals

23 views Asked by At

This is a Calculator I'm building. Whenever I try to do small subtractions or addition (e.g. 7.8 - 7.6) it shows up a very long strand of unnecessary decimals (0.20000000000000018).

You can find the entire code here https://github.com/Fallingstar-0/Calculator.

I have tried Math.floor, Math.ceil; but nothing works. I looked up on the internet and it seems it's one of JS's shenanigans.

For easier readability I'll post the snippet below:

const formatter = new Intl.NumberFormat(undefined, {
  maximumFractionDigits: 0,
})

const format = (number) => {
  if (number == null) return
  const [integer, decimal] = number.split(".")
  if (decimal == null) return formatter.format(integer)
  return `${formatter.format(integer)}.${decimal}`
}

export const ACTIONS = {
  ADD_DIGIT: "add-digit",
  ADD_OPERATION: "add-operation",
  EVALUATE: "evaluate",
  CLEAR: "clear",
  DELETE_DIGIT: "delete-digit",
}

const reducer = (state, { type, payload }) => {
  if (type === ACTIONS.ADD_DIGIT) {
    if (state.overwrite) {
      return {
        ...state,
        currentOperand: payload.digit,
        overwrite: false,
      }
    }
    if(!state.currentOperand && payload.digit === ".") {
      return {
        ...state,
        currentOperand: `0.`
      }
    }
    if (payload.digit === "0" && state.currentOperand === "0") return state
    if (payload.digit === "." && state.currentOperand.includes(".")) {
      return state
    }
    return {
      ...state,
      currentOperand: `${state.currentOperand ?? ""}${payload.digit}`,
    }
  }
  if (type === ACTIONS.CLEAR) {
    return { state }
  }
  if (type === ACTIONS.ADD_OPERATION) {
    if (state.currentOperand == null && state.previousOperand == null) {
      return state
    }
    if (state.operation && state.currentOperand == null) {
      return {
        ...state,
        operation: payload.operation,
      }
    }
    if (state.previousOperand && state.currentOperand) {
      return {
        ...state,
        previousOperand: evaluate(state),
        operation: payload.operation,
        currentOperand: null,
      }
    }
    return {
      ...state,
      previousOperand: state.currentOperand,
      operation: payload.operation,
      currentOperand: null,
    }
  }
  if (type === ACTIONS.DELETE_DIGIT) {
    if (state.overwrite) {
      return {
        ...state,
        currentOperand: null,
        overwrite: false,
      }
    }
    if (!state.currentOperand) {
      return state
    }
    if (state.currentOperand.length === 1) {
      return {
        ...state,
        currentOperand: null,
      }
    }
    return {
      ...state,
      currentOperand: state.currentOperand.slice(0, -1),
    }
  }
  if (type === ACTIONS.EVALUATE) {
    if (!state.currentOperand && !state.previousOperand) {
      return state
    }
    if (state.currentOperand && state.previousOperand) {
      return {
        ...state,
        currentOperand: evaluate(state),
        previousOperand: null,
        operation: null,
        overwrite: true,
      }
    }
  }
}
// evaluate function
const evaluate = ({ currentOperand, previousOperand, operation }) => {
  const prev = parseFloat(previousOperand)
  const curr = parseFloat(currentOperand)

  let computation = ""
  if (isNaN(prev) || isNaN(curr)) {
    return ""
  }
  switch (operation) {
    case "/":
      computation = prev / curr
      break
    case "*":
      computation = prev * curr
      break
    case "+":
      computation = prev + curr
      break
    case "-":
      computation = prev - curr
      break
  }
  return computation.toString()
}

function App() {
  const [{ currentOperand, previousOperand, operation }, dispatch] = useReducer(
    reducer,
    {}
  )
  return (
    <div>
       ...Rest of code
0

There are 0 answers