cp-documentation

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub zawa-tin/cp-documentation

:heavy_check_mark: 文字列で受け取った小数を10倍しまくって整数にするやつ
(Src/Utility/FloatingMarkerShift.hpp)

概要

文字列で受け取った小数を $10^t$ 倍して小数点を除去した整数にして返します。

引数は文字列 (std::string)である必要があります。

ライブラリの使い方

i64 FloatingMarkerShift(const std::string& S, u32 shift)

引数

const std::string& S

文字列として受け取った小数。

u32 shift

小数点を右に何回ずらすかを指定する。Sに対してshift回右に小数点をずらしても小数点以下が $0$ で無い場合はassertにひっかかって死ぬ


返り値

計算結果。符号付き64bit整数。


FloatingMarkerShift("1.23", 3) // 1230
FloatingMarkerShift("-0.01", 2) // -1


必要になった経緯

例えばこの問題 等で、浮動小数点型で入力を受け取ってそのまま $10$ 倍していって整数にした場合、誤差で死ぬ。

逆に、 $2$ 進数で値を保持しているということは $2$ 倍や $2$ で割るのにはかなり強(いらし)く、 例えばこの問題 では許容誤差が $10^{-9}$ とかなり厳しいが小数点以下が絡む割り算が $4$ しか無いので愚直にやっても普通にACが出た。

Depends on

Verified with

Code

#pragma once

#include "../Template/TypeAlias.hpp"

#include <string>
#include <cassert>
#include <limits>

namespace zawa {

i64 FloatingMarkerShift(const std::string& S, u32 shift) {
    static i64 lim10{std::numeric_limits<i64>::max() / 10};
    assert(not S.empty());
    i64 res{};
    u32 moved{};
    bool start{};
    bool minus{S[0] == '-'};
    for (u32 i{(u32)minus} ; i < S.size() ; i++) {
        if (S[i] == '.') {
            start = true;
        }
        else {
            if (start) moved++;
            assert(res < lim10);
            res = res * 10;
            assert(res < std::numeric_limits<i64>::max() - (S[i] - '0'));
            res += S[i] - '0';
        }
    }
    assert(moved <= shift);
    while (moved < shift) {
        moved++;
        assert(res < lim10);
        res = res * 10;
    }
    if (minus) res *= -1;
    return res;
}

}// namespace zawa
#line 2 "Src/Utility/FloatingMarkerShift.hpp"

#line 2 "Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "Src/Utility/FloatingMarkerShift.hpp"

#include <string>
#include <cassert>
#include <limits>

namespace zawa {

i64 FloatingMarkerShift(const std::string& S, u32 shift) {
    static i64 lim10{std::numeric_limits<i64>::max() / 10};
    assert(not S.empty());
    i64 res{};
    u32 moved{};
    bool start{};
    bool minus{S[0] == '-'};
    for (u32 i{(u32)minus} ; i < S.size() ; i++) {
        if (S[i] == '.') {
            start = true;
        }
        else {
            if (start) moved++;
            assert(res < lim10);
            res = res * 10;
            assert(res < std::numeric_limits<i64>::max() - (S[i] - '0'));
            res += S[i] - '0';
        }
    }
    assert(moved <= shift);
    while (moved < shift) {
        moved++;
        assert(res < lim10);
        res = res * 10;
    }
    if (minus) res *= -1;
    return res;
}

}// namespace zawa
Back to top page